select/poll/epoll

1、select的实现(fs/select.c)

主要涉及三个函数sys_select() à core_sys_select() à do_select() 

每次调用select,都会将用户态的fd拷贝至内核态

do_select()会

1) 循环遍历每一个fd,调用对应的驱动的poll函数,poll函数会:1)将用户进程插入到驱动的等待队列中 2)返回mask告知就绪fd

2) 如果遍历完都没有,for循环进入睡眠,等待被驱动唤醒或超时退出

3) 如果遍历完有可操作的fd,则跳出for循环

 

2、poll的实现(fs/select.c)

主要涉及三个函数sys_poll()->do_sys_poll()->do_poll()

poll的实现和select非常相似,区别就是入参方式变了,由固定大小的位图改成了变长的指针数组,select中存放文件描述符集合,是用的数组,poll中替换成了链表,这样就没有了1024的限制

 

3、epoll的实现(fs/eventpoll.c)

epoll机制是通过向驱动注册回调函数的方式获得IO就绪的通知

其使用过程如下:

第一步:epoll_create会创建一个对象, 该对象包含两个数据结构,一个红黑树,一个链表;

第二步:epoll_ctl会将要关注的fd存入红黑树数据结构,当有事件触发时,内核会将就绪的fd拷贝到链表数据结构

第三部:epoll_wait从链表里读取就绪的fd,移到用户空间

注意:epoll_create的入参需要填入一个任意的大于0的int, 该参数已无具体意义

 

总结:

(1)select支持的文件描述符有1024的限制,poll 没有限制

(2)select和poll实现机制相似,每次调用,都需要把fd集合从用户态拷贝到内核态,然后遍历所有的fd, 再拷贝回用户态

(3)epoll避免了fd在用户态和内核态间的反复拷贝, 其内部的回调机制,以及就绪链表的存在,使得在io数量超多的情况下,其效率比select/poll要高效很多

 

posted @ 2024-02-26 15:17  ho966  阅读(4)  评论(0编辑  收藏  举报