欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

selcet、epoll的实现机制以及epoll为什么高效?

程序员文章站 2022-05-12 11:27:08
...

IO多路复用模型通常有三种:poll、select、epoll

select一次事件处理的过程 : 需要两次拷贝和两次轮询(1次内核轮询、一次用户轮询)

  1. 从用户态拷贝 文件描述符数组 到内核态。(用户态->内核态的拷贝)
  2. 内核态需要遍历这个数组(轮询查看是否有事件准备就绪),如果有的话,会修改 拷贝到内核态的这个数组。(内核轮询)。
  3. 内核将就绪好的数组拷贝给用户。(内核态->用户态的拷贝)
  4. 因为内核已经将 数组中的数据修改了,所以用户又需要轮询一次,查看是哪些事件准备就绪了。(用户轮询)
  5. 下一次的话,用户又需要将文件描述符数组拷贝到内核态(因为内核中的那个数组已经被改了)。
    因此一次事件处理的过程,需要两次拷贝和两次轮询,而如果下一次事件处理,仍需两次拷贝两次轮询。

epoll一次需要最开始的一次拷贝,另一次内核到用户态的拷贝 数据量也不是很大;0次轮询。

  1. 内核创建一个红黑树节点,用来管理那些文件描述符。
  2. 用户将文件描述符数组 拷贝到内核空间,内核将文件描述符挂在树上。(用户态->内核态的拷贝)
  3. 内核使用回调机制,等事件准备就绪,返回给内核,内核将这些就绪事件添加到就绪链表中。(内核回调)
  4. 内核将就绪链表返回给用户,用户直接对就绪链表处理即可,不需轮询。
  5. 下次也并不需要将文件描述符数组拷贝到内核态,因为内核空间里有个红黑树节点在管理文件描述符。

epoll过程

epoll机制提供了三个系统调用epoll_create、epoll_ctl、epoll_wait

下面是这三个函数的原型

  • epoll_create
int epoll_create(int size);

此函数返回一个epoll的文件描述符

  • epoll_ctl
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

此函数是添加、删除、修改事件

epfd:epoll的文件描述符

op:表示选项,EPOLL_CTL_ADD(添加事件)、EPOLL_CTL_MOD(修改事件)、EPOLL_CTL_DEL(删除事件)

fd:要操作的文件描述符

event:事件信息

  • epoll_wait
int epoll_wait(int epfd, struct epoll_event *events,
               int maxevents, int timeout);

此函数是等待条件满足,放回值为准备就绪的事件数

epfd:epoll的文件描述符
events:返回的事件信息
maxevents:要等待的最大事件数
timeout:超时时间

  • epoll_event
struct epoll_event
{
  uint32_t events;		//epoll事件
  epoll_data_t data; 	//联合体,一般表示文件描述符
};

参考链接:
https://blog.csdn.net/weixin_42462202/article/details/95315926
https://blog.csdn.net/weixin_42462202/article/details/95377075

相关标签: 底层