原文地址:http://www.cppfans.org/1418.html
浅析epoll – epoll函数深入讲解
前一篇大致讲了一下epoll是个什么东西,优点等内容,这篇延续上一篇的内容,主要是分析epoll的函数,epoll高性能的深入分析。
epoll的三大函数
1.创建epoll fd函数
int epoll_create(int size); |
epoll_create()创建一个epoll的事例,通知内核需要监听size个fd。size指的并不是最大的后备存储设备,而是衡量内核内部结构大小的一个提示。当创建成功后,会占用一个fd,所以记得在使用完之后调用close(),否则fd可能会被耗尽。
Note:自从Linux2.6.8版本以后,size值其实是没什么用的,不过要大于0,因为内核可以动态的分配大小,所以不需要size这个提示了。
创建还有另外一个函数
int epoll_create1(int flag); |
这个函数是在linux 2.6.27中加入的,当你在看陈硕的muduo时可以看到这个函数,其实它和epoll_create差不多,不同的是epoll_create1函数的参数是flag,当flag是0时,表示和epoll_create函数完全一样,不需要size的提示了。
当flag = EPOLL_CLOEXEC,创建的epfd会设置FD_CLOEXEC
当flag = EPOLL_NONBLOCK,创建的epfd会设置为非阻塞
一般用法都是使用EPOLL_CLOEXEC.
Note:关于FD_CLOEXEC,现在网上好多都说的有点问题,我翻阅了一些资料,请教了一些人,大约明白它的意思了。
它是fd的一个标识说明,用来设置文件close-on-exec状态的。当close-on-exec状态为0时,调用exec时,fd不会被关闭;状态非零时则会被关闭,这样做可以防止fd泄露给执行exec后的进程。关于exec的用法,大家可以去自己查阅下,或者直接man exec。
2.epoll事件的注册函数
int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event); |
select是在监听时告诉内核要监听的事件,而epoll_ctl是先注册需要监听的事件。
第一个参数epfd,为epoll_create返回的的epoll fd。
第二个参数op表示操作值。有三个操作类型,
EPOLL_CTL_ADD // 注册目标fd到epfd中,同时关联内部event到fd上 EPOLL_CTL_MOD // 修改已经注册到fd的监听事件 EPOLL_CTL_DEL // 从epfd中删除/移除已注册的fd,event可以被忽略,也可以为NULL |
第三个参数fd表示需要监听的fd。
第四个参数event表示需要监听的事件。
typedef union epoll_data { struct epoll_event { |
event参数是一个枚举的集合,可以用” | “来增加事件类型,枚举如下:
EPOLLIN:表示关联的fd可以进行读操作了。
EPOLLOUT:表示关联的fd可以进行写操作了。
EPOLLRDHUP(since Linux 2.6.17):表示套接字关闭了连接,或者关闭了正写一半的连接。
EPOLLPRI:表示关联的fd有紧急优先事件可以进行读操作了。
EPOLLERR:表示关联的fd发生了错误,epoll_wait会一直等待这个事件,所以一般没必要设置这个属性。
EPOLLHUP:表示关联的fd挂起了,epoll_wait会一直等待这个事件,所以一般没必要设置这个属性。
EPOLLET:设置关联的fd为ET的工作方式,epoll的默认工作方式是LT。
EPOLLONESHOT (since Linux 2.6.2):设置关联的fd为one-shot的工作方式。表示只监听一次事件,如果要再次监听,需要把socket放入到epoll队列中。
3.epoll等待事件函数
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); |
上面两个函数的参数含义:
第一个参数:表示epoll_wait等待epfd上的事件
第二个参数:events指针携带有epoll_data_t数据
第三个参数:maxevents告诉内核events有多大,该值必须大于0
第四个参数:timeout表示超时时间(单位:毫秒)
epoll_pwait(since linux 2.6.19)允许一个应用程序安全的等待,直到fd设备准备就绪,或者捕获到一个信号量。其中sigmask表示要捕获的信号量。
函数如果等待成功,则返回fd的数字;0表示等待fd超时,其他错误号请查看errno
函数到这里就讲完了,下一篇会写一个例子给大家看下这些函数是如何使用的。