Linux 编程】 I/O复用函数
三组I/O复用函数:select, poll, epoll
select
在一段时间内监听用户感兴趣的文件描述符上的可读、可写和异常等事件。
#include <sys/select.h>
#include <sys/time.h>
int select(int max_fd, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout) // select 系统调用
FD_ZERO(int fd, fd_set* fds) //清空集合
FD_SET(int fd, fd_set* fds) //将给定的描述符加入集合
FD_ISSET(int fd, fd_set* fds) //将给定的描述符从文件中删除
FD_CLR(int fd, fd_set* fds) //判断指定描述符是否在集合中
poll
在一定事件内轮训一定数量的文件描述符,以测试其中是否有就绪者
poll 函数原型:
epoll
epoll 在Linux2.6内核正式提出,是基于事件驱动的I/O方式。 epoll 与 poll 和 select 有很大差异
- epoll 使用一族函数完成指令
- epoll 将用户关心的事件描述符的事件放在内核的一个事件表中,无须像 select 和 poll 每次调入重复传入的文件描述符或者事件集
// epoll api
#include<sys/epoll.h>
/* 函数创建 */
int epoll_create(int size); // size 指定事件的大小
/* 事件表的操作 */
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
/* epoll_wait 函数在一段超时时间内等待一组文件描述符上的事件 */
// epoll_wait 函数如果检测到事件,就将所有就绪的事件从内核事件表(由 epfd 参数指定)中复制到第二个参数 events 指向的数组只能
int epoll_wait(int epfd, struct epoll_event *event, int maxevents, int timeout);
poll 和 epoll 在使用上的差别【怎样索引到返回的就绪文件描述符】
poll 必须遍历所有已注册的文件描述符并找出其中的就绪者(也可稍作优化);
epoll 只需遍历就绪的 若干个文件描述符。
epoll 对文件描述符操作的两种方式 LT 和 ET 模式
LT (Level Trigger, 条件触发)
ET(Edge Trigger, 边沿触发)
event.events = EPOLLIN | EPOLLET
LT 和 ET 的区别在于发生事件的时间点。LT 方式中,只要输入缓冲有数据就会一直通知该事件,因此会多次调用 epoll_wait 函数;ET 方式中输入缓冲收到数据时仅注册1 次该事件。 ET 模式很大程度上减少了epoll事件的触发次数,因此效率比 LT 模式下高。
select 和 poll 函数都是 LT模式, epoll 函数可以选择是 LT 还是 ET 模式。ET 方式中一定要采取非阻塞的 read 和 write 函数。
I/O复用的比较
Linux下I/O多路复用系统调用(select, poll, epoll)介绍
参考:
Linux 高性能服务器编程 游双著