select原理
说在前面,整个select在内核空间中的工作事实上非常有趣,中间还会穿插一些可抢占点,检测当前是否有进程可以调度,增加系统的实时性
初始化阶段:
FD_set,把要监听的fd都添加到监听集合中去
监听阶段:
调用select()
通过系统调用,会把监听集合中所有fd都copy到kernel space,并填充fds数据结构
调用poll_initwait(),(作用待探究)
(第一次遍历!)遍历fds中有效的fd,判断fd对应的文件有没有打开,如果打开了就调用设备文件节点对应的driver中的poll
这个poll做的事情是把当前进程挂到对应driver的等待队列中,并设置一个回调函数(当数据到了,有数据可读,则触发硬件中断,并在硬件中断处理中调用回调函数,从而唤醒这个driver的等待队列中的进程去对数据进行操作)
在do_select中调用schedule_timeout挂起进程,当数据来了,driver中断处理调用wake_up来唤醒进程,也是返回到这个time_out这里
(第二次遍历!)从schedule_timeout返回后又要重新遍历fd,给有事件发生的fd添加一个mask掩码
把fd复制回userspace
从select()返回
数据处理阶段:
(FD_ISSET)通过FD_ISSET()判断是什么fd可读/可操作,从而去进行数据处理
总结:
以上这个过程一般放在一个for(;;)中,也就是说会重复调用select,这个过程会发生多次内核态和用户态的切换和数据拷贝,此外,还有两次对全部fd的遍历,当fd数量上来以后,性能上的损耗就会非常大。
标签:调用,epoll,driver,遍历,fd,IO,poll,select From: https://www.cnblogs.com/jiayu-code/p/16641957.html