事件驱动模型的epoll

2025-05-18 05:48:35
推荐回答(1个)
回答1:

epoll是和上面的poll和select不同的一个事件驱动库,它是在linux 2.5.44中引入的,它属于poll的一个变种。上面的poll和select库,它们的最大的问题就在于效率。它们的处理方式都是创建一个事件列表,然后把这个列表发给内核,返回的时候,再去轮询检查这个列表,这样在描述符比较多的应用中,效率就显得比较低下了。一种比较好的做法是,把描述符列表交给内核,一旦有事件发生,内核把发生事件的描述符列表通知给进程,这样就避免了轮询整个描述符列表。epoll就是这样一种模型。下面对epoll的使用进行说明:
(1).创建一个epoll描述符,调用epoll_create()来完成,epoll_create()有一个整型的参数size,用来告诉内核,要创建一个有size个描述符的事件列表(集合)
int epoll_create(int size)
(2).给描述符设置所关注的事件,并把它添加到内核的事件列表中去,这里需要调用epoll_ctl()来完成。
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
这里op参数有三种,分别代表三种操作:
a. EPOLL_CTL_ADD, 把要关注的描述符和对其关注的事件的结构,添加到内核的事件列表中去
b. EPOLL_CTL_DEL,把先前添加的描述符和对其关注的事件的结构,从内核的事件列表中去除
c. EPOLL_CTL_MOD,修改先前添加到内核的事件列表中的描述符的关注的事件
(3). 等待内核通知事件发生,得到发生事件的描述符的结构列表,该过程由epoll_wait()完成。得到事件列表后,就可以进行事件处理了。
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout)
在使用epoll的时候,有一个需要特别注意的地方,那就是epoll触发事件的文件有两种方式:
(1)Edge Triggered(ET),在这种情况下,事件是由数据到达边界触发的。所以要在处理读、写的时候,要不断的调用read/write,直到它们返回EAGAIN,然后再去epoll_wait(),等待下次事件的发生。这种方式适用要遵从下面的原则:
a. 使用非阻塞的I/O;b.直到read/write返回EAGAIN时,才去等待下一次事件的发生。
(2)Level Triggered(LT), 在这种情况下,epoll和poll类似,但处理速度上可能比poll快。在这种情况下,只要有数据没有读、写完,调用epoll_wait()的时候,就会有事件被触发。