epoll模型

二、epoll系统调用:

1、为什么会有epoll?

     select和poll系统调用当有事件发生之后返回给我们但是它们俩返回的是发生事件的个数,我们并不知道具体是哪一个描述符发生了什么事,必须去一个轮询,那么当描述符的数量较多的时候,效率很明显就会降低,而epoll函数是使用一组函数来完成任务,而不是单个函数,其次,epoll把用户关心的文件描述符上的事件放在内核里的一个事件表中,从而无须像select和poll那样每次调用都要重复传入文件描述符集或事件集。但epoll需要使用一个额外的文件描述符,来唯一标识内核中的这个事件表,这个文件描述符使用如下epoll_create函数来创建:

#include<sys/epoll.h>

int epoll_create(int size)   //创建一个事件表,该事件表在内核中,在使用完epoll之后,需要对它进行close,否则会导致fd太多导致耗尽。

size参数现在并不起作用,只是给内核一个提示,告诉它事件表需要多大。该函数返回的文件描述符将用作其他所有epoll系统调用的第一个参数,以指定要访问的内核事件表。

2、操作epoll内核事件表的函数:

int epoll_ctl(int epfd, int op,  int fd,  struct epoll_event *event)  //事件注册函数,将fd,添加、修改、删除到epfd中,通过op参数修改

fd:是要操作的文件描述符,op参数则指定操作类型。操作类型有如下3种:

EPOLL_CTL_ADD:往事件表种注册fd上的事件

EPOLL_CTL_MOD:修改已经注册的fd的监听事件

EPOLL_CTL_DEL:从epfd中删除一个fd

event参数指定事件,它是epoll_event结构指针类型。epoll_event的定义如下:

struct epoll_event

{__uint32_t events;   //描述事件类型        epoll_data_t data; //用于存储用户数据};

epoll_data_t(是个联合体)的定义如下:

typedef union epoll_data

{ void *ptr;//可用来指定与fd相关的用户数据   int fd;//指定事件所从属的目标文件描述符}

3、epoll系列系统调用的主要接口是epoll_wait函数。它在一段超时时间内等待一组文件描述符上的事件,原型如下:

int epoll_wait( int epfd, struct epoll_event *events, int maxevents, int timeout);//可以理解为收集epoll监控的所有事件中,已经发生的那部分fd的数量

该函数成功时返回就绪的文件描述符的个数,失败时返回-1并设置errno

maxevents参数指定最多监听多少个事件,它必须大于0。

epoll_wait函数如果检测到事件,就将所有就绪的事件从内核事件表(由epfd参数指定)中复制到它的第二个参数events指向的数组中。这个数组只用于输出epoll_wait检测到的就绪事件,而不像select和poll的数组参数那样既用于传入用户注册的事件,又用于输出内核检测到的就绪事件。这就极大的提高了应用程序索引就绪文件描述符的效率。

4、epoll触发方式:

epoll支持ET和LT两种触发方式:LT:电平触发模式、ET:边沿触发模式

1)采用LT工作的描述符,当epoll_wait检测到其上有事件发生并将此事件通知应用程序后,应用程序可以不立即处理该事件,这样,当应用程序下一次调用epoll_wait时,epoll_wait还会再次向应用程序通告此事件,直到该事件被处理。(只要缓冲区有数据,就会不停的发送就绪通知)

2)采用ET工作模式的文件描述符,当epoll_wait检测到其上有事件发生并将此事件通知应用程序后,应用程序必须立即处理该事件,因为后续的epoll_wait调用将不再向应用程序通知这一事件(当一个fd缓冲区就绪的时候,只会发送一次事件触发,而不会管缓冲区的数据是否已经被读取,都不会再发送第二次)。可见ET模式再很大程序上降低了同一个epoll事件被重复触发的次数,因此效率要比LT模式高。

5、epoll工作原理:

1)在调用epoll_create之后,内核就已经创建了一个红黑树结构体,一个list双向链表,在内核态准备接受存储需要监控的fd。

2)在调用epoll_ctr之后,直接向内核态的eventpoll进行add/mod/del对应的fd,对于新添加进来的fd,重复的fd可以通过eventpoll红黑树识别出来,而不需要再次从用户态拷贝到内核态这个过程。

3)同时epoll还维护了一个双向的list链表,在epoll_ctr执行的时候,除了会向eventpoll红黑树添加修改外,还会在内核中断处理程序中注册一个回调函数,告诉内核,当这个fd就绪之后,将他放到list里面去。

4)在epoll_wait调用的时候,就是观察这个双向list是否有数据,有就直接处理即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值