操作系统: 08 2009存档

      “书非借不能读也”,从图书馆借了《linux设备驱动开发详解》,虽然时间紧迫,但还是重点看了里面的前几章,包括块设备驱动,其它章节不太可能用到,飘过。
      总体感觉是写得比较详细的,例子也很具体,如果是学嵌入式做驱动的人很适合;但缺点也就是大而全,厚厚的一本,幸亏是借的,要是买的心痛死了。个人觉得可 以和《linux设备驱动程序(第三版)》一起学习,效果应该不错。不过最好也最便宜的驱动学习方法还是去看linux源代码,比如ext3。
      最近做项目用了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     }