Chinaunix首页 | 论坛 | 博客
  • 博客访问: 322136
  • 博文数量: 85
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 800
  • 用 户 组: 普通用户
  • 注册时间: 2014-10-18 15:21
文章分类

全部博文(85)

文章存档

2017年(1)

2016年(19)

2015年(55)

2014年(10)

我的朋友

分类: 嵌入式

2015-04-04 19:29:37

最近学习Poll花了一些时间去了解Linux内部的机制,主要是看了下韦东山老师的关于这个Poll总结后,感觉还是有些疑惑,一番纠结后终于有些明朗了。所以写写总结分享下。
一、Poll应用程序接口

函数原型:int poll(struct pollfd    *fds ,nfds_t    nfds ,int    timeout);

fds为指向待查询的设备文件数组;

nfds描述第一个参数fds中有多少个设备;

timeout为查询不到我们期望的结果进程睡眠的时间;

返回值:查询到期望状态的设备文件个数


struct pollfd {     

                         int fd;              /* 文件描述符 */ (待查询的设备)

                   short events;   /* 等待的事件 */(待查询的设备的状态)

                   short revents;  /* 实际发生了的事件 */

              }

总的来说,Poll提供的接口工作机制如下:

应用程序中调用poll查询文件的状态,首先将fds里面的每个设备文件fd取出,调用它们驱动程序的poll函数,查询是否出现我们期望状态,查询完fds里面所有的设备文件得到满足期望状态的设备文件的数量,如果这个数为0,则poll调用将导致进程就进入睡眠状态,睡眠时间由poll函数设定,如果程序在睡眠状态中fds的某个文件出现我们期望状态,那么poll立即返回,否则一直睡眠到睡眠时间结束为止,返回值为0;如果这个数大于0 ,poll返回满足条件的设备数量。

poll相当于open("/dev/xxx",O_RDWR)阻塞打开文件,区别在于当设备文件无数据可读时poll只导致程序休眠固定时间,而open将导致程序一直休眠到有数据为止。

至于更为详细的内核代码分析,抓住如下主线即可明白了,
(应用程序)poll->sys_poll->do_sys_poll->do_poll->do_pollfd->f_op->poll(驱动)
这里不再贴

二、驱动程序

驱动程序里与poll相关的地方有两处:
一是构造file_operation结构时,要定义自己的poll函数。
二是在poll函数中通过poll_wait来调用上面说到的__pollwait函数

staticinline void poll_wait(struct file * filp, wait_queue_head_t * wait_address,poll_table *p)
执行到驱动程序的poll_wait函数时,进程并没有休眠,我们的驱动程序里实现的poll函数是不会引起休眠的。
让进程进入休眠,是前面分析的do_sys_poll函数的30行“__timeout = schedule_timeout(__timeout)”。

poll_wait只是把本进程挂入某队列中,该队列由poll内部提供,应用程序调用poll > sys_poll> do_sys_poll > poll_initwait,do_poll > do_pollfd > 我们自己写的poll函数后,再调用schedule_timeout进入休眠。如果我们的驱动程序发现情况就绪,可以把这个队列上挂着的进程唤醒。
这里就有几个疑问:
1.我们自定义的驱动程序在对应的一个描述符中,经过了Poll等待超时返回后是被调用了几次?
2.在驱动中若不调用poll_wait会怎么样?

第一个问题:
可以在定义的驱动poll函数中插入打印语句,看它打印出几条信息。可以发现,在一次超时返回时,打印出了2条,而这两条分别是进入休眠前后被唤醒时调用了驱动poll函数而打印出的。
所以第一个问题,2次。

第二个问题:
不调用poll_wait则不把本进程加入到队列中,则没办法被唤醒,需要靠其它地方的唤醒机制,比如中断。
笔者测试了按键驱动中把自带的驱动poll函数中的poll_wait注释掉后,则按键似乎失去了实时反应,只有在按键按下长时间时才会发现。




阅读(1910) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~