系统相关
首页 > 系统相关> > linux事件监听机制epoll

linux事件监听机制epoll

作者:互联网

说明:linux 下的事件监听机制主要有 poll ,select,epoll ,这里主要介绍epoll 机制,以及可以完美配合使用的eventfd

epoll : kernel source/linux/fd/eventpoll.c

系统调用:

 

int epoll_create(int size);       //底层实现调用的是epoll_create1(0) ,size内核实现是没有使用的但是有判断不能小于0
int epoll_create1(int flags);      // flags: EPOLL_CLOEXEC
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);      //op: EPOLL_CTL_ADD/EPOLL_CTL_MOD/EPOLL_CTL_DEL

int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);       // 0 < maxevents <= MAX_INT/sizeof(struct epoll_event)
int epoll_pwait(int epfd, struct epoll_event *events,int maxevents, int timeout,const sigset_t *sigmask);   //和epoll_wait的不同是可以选择屏蔽某些信号中断

epoll 实现机制

  1. 通过epoll_create创建一个epollfd文件描述符.kernel里通过struct eventpoll结构体管理epoll的数据(2,3里的红黑树,双向链表都由这个顶层的结构体管理);
  2. 通过epoll_ctl(EPOLL_CTL_ADD 为例)将准备监听的设备描述符插入管理事件监听的红黑树上;

    (1)fd ADD 的时候会注册一个回调函数1

    (2)调用监听设备具体实现的poll()函数,执行回调函数1(将等待队列加到唤醒链表里)

    (3)将新加入的设备描述符等信息打包(struct epitem)插入到红黑树里

 3.调用epoll_wait 等待事件到来.有事件到来后会插入到一个管理ready 事件的链表里,epoll_wait 通过检测这个链表来唤醒当前睡眠的进程,链表不为空唤醒进程,用户取到对应的数据(fd,事件类型 ...)

 4.何时将ready 的事件加入到链表里? 2步注册的回调函数里又注册了一个回调函数,在事件唤醒时通过 wake_up_locked_poll 等接口调用到回调函数.回调函数实现将准备好的事件加入到ready链表里.

 

poll /select /epoll 对比

总结:

在监听的设备很少,但是事件频繁发生的情况下使用poll,select效率会高些,epoll 适合监听大量的设备,每个设备上发生的事件频率较低,因为epoll 内部的回调有开销.

eventfd

kernel source/linux/fs/eventfd.c

系统调用:

int eventfd(unsigned int initval, int flags);

read/write..

机制:

  1. eventfd()接口创建一个eventfd ,内核里面分配并初始化一个struct eventfd_ctx结构体,主要涉及到的是里面一个u64 count, eventfd()的第一个参数是这个count的初始值.
  2. 用户每次调用write会将这个count+n (n:write 写进去的值),调用read 会将count 的值返回,并将count-1 或者-count, 根据eventfd()的第二个参数flags ?=EFD_SEMAPHORE 决定,默认是一次减count
  3. 内核里实现里这个eventfd的poll (eventfd_poll)和eventfd_signal ,poll 用于监控count 的值,count 大于0 表示evnetfd 有POLLIN事件,signal用于触发唤醒事件,即将count+n
  4. 用户使用eventfd的poll.需要在监听前将eventfd 通过具体设备的ioctl传打到内核和对应的驱动对应起来,具体设备驱动中在有事件中断时调用eventfd_signal唤醒当前休眠的进程,使上层的poll 成功返回

总结:

将eventfd作为监听的设备描述符加入到epoll的监听树中,可以不占用具体设备的poll接口,不需要实现设备的poll函数和唤醒机制.

 

标签:count,epoll,int,eventfd,linux,poll,监听
来源: https://blog.csdn.net/lehuihui/article/details/112664716