linux下poll和epoll内核源代码剖析

      最近做项目用了epoll,于是打算深究一下,看了看linux内核的代码,凑成浅文一篇,欢迎指正。

       《poll和epoll内核源码剖析》(一)
       《poll和epoll内核源码剖析》(二)
       《poll和epoll内核源码剖析》(三)

      ====== 2010.5.14 ======

      基于qixinkui同学的疑问,我修改了“poll是轮询”这一错误提法(在第二篇里),然后增加了对EPOLLET的代码分析(第三篇)。poll和epoll的区别在于fd数量很大时,两者的事件模型效率不同,而NAPI,它是驱动程序的功能,只会影响某个fd的通知速度,所以这里就不补充讨论了。有了NAPI,对poll和epoll都一样有利。
  
      ====== 2010.6.8 ======
      问:当你讲sys_epoll_wait()->ep_poll()这个函数时,里面有个for循环。你说它除了睡觉和判断ep->rdllist是否为空外什么也没干。我的疑问是既然它睡觉了,也就是阻塞了,它还怎么进行判断?这两者的关系是怎样的?
      答:下面的代码是ep_poll里的那个“循环”,1531行的代码是判断rdllist是否为空的,1539行是睡觉用的。
      你所说,睡觉了,也就阻塞了,也就是1539行的schedule_timeout,当前进程自动放弃CPU,但是,是用的schedule_timeout而不是schedule。用了schedule,当前进程放弃CPU,直到内核在以后的某次进程调度中重新选择该进程;而schedule_timeout,那就是经过一个时间后(这里是jtimeout),进程会重新被唤醒获得CPU,然后从schedule_timeout函数返回。返回后继续循环,继续判断rdllist是否为空,为空就接着 schedule_timeout......
      说白了,这个“睡觉”,不是永远睡下去,是一定会醒来的,醒来了再接着判断。不是说他边睡觉边判断。

 1524         for (;;) {
 1525             /*
 1526              * We don't want to sleep if the ep_poll_callback() sends us
 1527              * a wakeup in between. That's why we set the task state
 1528              * to TASK_INTERRUPTIBLE before doing the checks.
 1529              */
 1530             set_current_state(TASK_INTERRUPTIBLE);
 1531             if (!list_empty(&ep->rdllist) || !jtimeout)
 1532                 break;
 1533             if (signal_pending(current)) {
 1534                 res = -EINTR;
 1535                 break;
 1536             }
 1537
 1538             write_unlock_irqrestore(&ep->lock, flags);
 1539             jtimeout = schedule_timeout(jtimeout);
 1540             write_lock_irqsave(&ep->lock, flags);
 1541         }
 1542         __remove_wait_queue(&ep->wq, &wait);
 1543
 1544         set_current_state(TASK_RUNNING);
 1545     }


相关文章

分类

7 Comments

hoterran said:

写的真好,看了很多遍了~~

DongHao Author Profile Page said:

过奖了,流水账而已

qixinkui said:

poll 是自己挨个去问每个fd“好没有?”、“好没有?“(poll),而epoll是给了每个fd一个命令“好了就调我的函数!”,然后就去睡了,等着设备驱动通知它....epoll的方法显然更英明、更高效。

请问,怎么我看过文章之后,感觉 poll 和 epoll 都是使用了回调函数的方式,poll并不是轮询的方式(“好没有?”“好没有?”)?

另外,对于epoll 支持的 edge trigger 方式的高效原因所在也没有讲出来。是否有新的研究可以解释一下这部分的内容?

另,对于kernel 驱动程序的 NAPI架构(结合使用了中断和轮询),对于这里的性能有没有什么影响?

谢谢,麻烦楼主作答。

mice said:

写得不错,楼主对代码研究很深入,讲解要点准确到位。顶!!

769155709 said:

epoll ET 那里解释说,把没有标上EPOLLET”(标红代码)且“事件被关注”的fd被重新放回了rdllist。,假如复制回的fd上次关注的事件为EPOLLIN,如果read把该fd的缓冲区内容读完,该fd会自动从就绪rdllist删除,重新把该进程挂入相关的fd事件等待队列?

chobit_s said:

- &(pwq->pt)->qproc = __pollwait; /*此行已经被我“翻译”了,方便观看*/
+(&(pwq->pt))->qproc = __pollwait; /*此行已经被我“翻译”了,方便观看*/

aaaa said:

写的很不错哦

留言:

关于文章

This page contains a single entry by DongHao published on 08 12, 2009 3:25 PM.

制作rpm之spec文件小提示 was the previous entry in this blog.

大师? is the next entry in this blog.

Find recent content on the main index or look in the 存档 to find all content.