邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛
分类: LINUX
2015-11-09 10:44:47
1. poll机制功能
函数原型:int poll(struct pollfd *fds,nfds_t nfds,int timeout);
fds为指向待查询的设备文件数组;
nfds描述第一个参数fds中有多少个设备;
timeout为查询不到我们期望的结果进程睡眠的时间;
返回值:查询到期望状态的设备文件个数
struct pollfd {
int fd; /* 文件描述符 */ (待查询的设备)
short events; /* 等待的事件 */(待查询的设备的状态)
short revents; /* 实际发生了的事件 */
}
功能过程描述:
poll相当于open("/dev/xxx",O_RDWR)阻塞打开文件,区别在于当设备文件无数据可读时poll只导致程序休眠固定时间,而open将导致程序一直休眠到有数据为止。
应用程序中调用poll查询文件的状态,首先将fds里面的每个设备文件fd取出,调用它们驱动程序的poll函数,查询是否出现我们期望状态,查询完fds里面所有的设备文件得到满足期望状态的设备文件的数量,如果这个数为0,则poll调用将导致进程就进入睡眠状态,睡眠时间由poll函数设定,如果程序在睡眠状态中fds的某个文件出现我们期望状态,那么poll立即返回,否则一直睡眠到睡眠时间结束为止,返回值为0;如果这个数大于0,poll返回满足条件的设备数量。
2. poll应用举例
点击(此处)折叠或打开
3. poll内核实现过程(kernel-2.6.30.4)
(应用程序)poll->sys_poll->do_sys_poll->do_poll->do_pollfd->f_op->poll(驱动)
在do_poll中:
for (;;)
{ //逐个取出待查询数组中的每个文件描述符来查询
for (; pfd != pfd_end; pfd++)
{
if (do_pollfd(pfd, pt))
{
count++;
pt = NULL;
}
}
pt = NULL;
if (!count)//如果没有一个设备文件发生可读
{
count = wait->error;
if (signal_pending(current))
count = -EINTR;
}
if (count || timed_out)//超时或者有设备文件可读,程序直接返回
break;
if (end_time && !to)
{
expire = timespec_to_ktime(*end_time);
to = &expire;
}
//程序睡眠
if (!poll_schedule_timeout(wait, TASK_INTERRUPTIBLE, to, slack))
timed_out = 1;
}
在do_pollfd中:
if (file->f_op && file->f_op->poll)
mask = file->f_op->poll(file, pwait);//调用设备的poll函数,返回是否发生期望的设备状态
在f_op->poll中(针对按键驱动举例):
unsigned int mask = 0;
poll_wait(file, &button_waitq, wait); //将当前的设备加入到等待队列中,当它不是马上就休眠
if (ev_press)
mask |= POLLIN | POLLRDNORM;//返回设备文件现在的状态
return mask;