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