select、epoll源码剖析与对比

来源:互联网 发布:u盘恢复数据多少钱 编辑:程序博客网 时间:2024/06/07 01:43

IO复用就是通过一组函数来监听多个文件描述符。程序只需要关注是否有文件描述符就绪即可。

在Linux下,有select、poll、epoll等IO复用函数。

select是指,在用户空间创建一个fd_set用于存放需要监听的文件描述符,每次调用select的时候需要将被监听的文件描述符全部拷贝给内核,而内核会进行轮询监听,查看是否有就绪的文件描述符。一旦发现文件描述符准备就绪,就会将更改过的监听情况返回给用户态,而用户态则需要进行位操作判断哪个文件描述符就绪,每次都需要重新传递新的拷贝情况。

epoll是指,在用户空间和内核空间开辟一块内存用于存放文件描述符的集合。然后在调用epoll_init的时候,注册一个新的文件系统,这应该是epoll返回一个epfd的原因吧。然后会开辟两块缓存,一块用于分配epoll_item红黑树的节点的具体的结构体,一块用于分配epoll_entry等待队列节点。开辟缓存的原因是epoll内核需要维护一个红黑树和就绪链表,所以会设计大量的空间分配。调用epoll_create的时候,底层调用sys_epoll_create(int size),这里传递的size只是一个建议。首先调用ep_getfd创建新的inode节点,新的file指针,新的fd并且将他们关联起来。然后调用d_alloc为inode分配一个dentry实体。之后调用ep_file_init创建一个新的eventpoll结构体并且初始化他,并将文件指针的数据域指向它,其中,eventpoll结构体主要包括一颗红黑树,一个就绪链表,一个读写锁。sys_epoll_ctl函数会根据宏定义的不同,选择具体的操作,首先根据eventpoll结构体中红黑树的根进行查找ep_find,这时,如果是插入,创建一个epoll_item节点并且进行挂载,创建epoll_entry并且加入到等待队列,设置回掉函数。当操作完成时,调用回掉函数,加入完成队列。epoll_wait,每次检查epitem中有没有已经完成的事件,有则返回,没有则等待,直到超时。

总结一下就是,系统内核创建一颗红黑树用于保存需要监听的文件描述符,使用mmap开辟一块在内核态和用户态中间的内存用于传递文件描述符,每个文件描述符在插入树的时候就已经注册一个回掉函数,当设备检测到该文件描述符上有事件发生的时候,通过该回掉函数返回,并将该描述符插入到系统准备好的就绪链表当中,而epoll_wait只需要检测链表中是否有数据即可。

原创粉丝点击