epoll_ctl 函数(译)
http://man7.org/linux/man-pages/man2/epoll_ctl.2.html
梗概:
#include <sys/epoll.h> int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
描述
该系统调用 执行epoll实例epfd上的操作,它需要具体执行的操作op以及被op执行的目标文件描述符 fd.
有效的op 参数如下:
- EPOLL_CTL_ADD
注册的文件描述符df在 epfd 上,把event事件和fd绑定在一起。
- EPOLL_CTL_MOD
修改注册到fd参数上的监听事件
- EPOLL_CTL_DEL
从epfd中删除fd,这里event参数可以没有,用NULL
参数 event 描述的是fd对象的变化,epoll_event 结构体定义如下
typedef union epoll_data { void *ptr; int fd; uint32_t u32; uint64_t u64; } epoll_data_t; struct epoll_event { uint32_t events; /* Epoll events */ epoll_data_t data; /* User data variable */ };
events 是一个使用如下参数的位集合。
- EPOLLIN
关联的文件可以执行read 操作
- EPOLLOUT
关联的文件可以进行写操作
- EPOLLRDHUP (Linux 2.6.17之后有)
socket刘关闭连接或则是关闭写半连接()
- EPOLLPRI
有紧急的数据需要去读
- EPOLLERR
有错误在关联的文件上发生,epoll_wait 总是等这种事件发生,并不需要在events中设置。此时接口可写。
- EPOLLHUP
关联的文件描述符挂断了。epoll_wait 会处理这种情况,不需要特意在events中设置,注意,当从信道或者socket流中读取的时候,这个时间紧紧只是说,连接被关闭了,从该管道中读取,当全部数据读取完的时候,才会返回0,即文件结束。此时接口可写。
- EPOLLET
设置关联的文件描述符上的边界触发信号,epoll默认的是水平触发。
- EPOLLONESHOT(linux 2.6.2之后的版本)
为关联的文件描述符设置一次监听,也就是说,触发了事件之后,文件描述符就从epoll_wait的等待队列中剔除,用户必须再次调用epoll_ctl,使用EPOLL_CTL_MOD 才可以重新事件掩码。
- EPOLLWAKEUP(Linux 3.5之后)
如果EPOLLONESHOT和EPOLLET被清除,并且进程有被CAP_BLOCK_SUSPEND ,确保系统不会在处理或者 等待中 进入挂起或者休眠的状态,在第一次在该文件描述符上调用了epoll_wait,第二次调用之前,在关闭文件描述之前,在通过EPOLL_CTL_DEL 移除事件之前,或者是通过EPOLL_CTL_MOD 移除EPOLLWAKEUP 之前, 在该事件会被一直认为在处理中。
返回值
成功执行后,epoll_ctl 返回0,发生错误的时候,epoll_ctl返回-1,并且errno 会被设置成合适的值。
可能的错误情况
- EBADF epfd 或者df 不是正确的文件描述符。
- EEXIST op 是EPOLL_CTL_ADD,并且fd已经被注册在该epoll实例 epfd上面了。
- EINVAL epfd 不是 epoll文件描述或者fd和epfd一样,或者请求的op并不支持该接口。
- ENOENT op 是EPOLL_CTL_MOD 或者是EPOLL_CTL_DEL,并且df 并没有被注册到该epoll 实例上。
- ENOSPC 在EPOLL_CTL_ADD的时候被 /proc/sys/fs/epoll/max_user_watches 强制限制
- EPERM fd并不支持epoll,这种错误可能发生在一个fd是一个正常文件或者是一个目录的时候。
版本
epoll_ctl 是在linux 2.6之后加进去的。
Leave a comment