Chinaunix首页 | 论坛 | 博客
  • 博客访问: 810505
  • 博文数量: 281
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2770
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-02 19:45
个人简介

邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛

文章分类
文章存档

2020年(1)

2018年(1)

2017年(56)

2016年(72)

2015年(151)

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

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


2.
poll应用举例

点击(此处)折叠或打开

  1. int main(int argc, char **argv)

  2. {

  3.       int fd;

  4.       unsigned char key_val;

  5.       int ret;

  6.       struct pollfd fds[1]; //查询数组的大小,这里我们仅查询一个设备文件

  7.       fd = open("/dev/buttons", O_RDWR);

  8.       if (fd < 0)

  9.           printf("can't open!\n");

  10.       fds[0].fd = fd;//查询的设备文件描述符为fd,也就是查询的设备是/dev/buttons

  11.       fds[0].events = POLLIN;//查询事件是POLLIN,也就是/dev/buttons是否按下

  12.       while (1)

  13.       {

  14.            ret = poll(fds, 1, 5000);//查询的设备队列是fds,里面有1个设备,查询不到就睡眠5s,在睡眠中如果有期望状态出现也是可以返回

  15.            if (ret == 0)

  16.               printf("time out\n"); //没有查询到按键按下,睡眠中也没有按键按下

  17.            else

  18.               {

  19.                   read(fd, &key_val, 1); //查询到按键按下,读取这个按键的值

  20.                   printf("key_val = 0x%x\n", key_val);

  21.               }

  22.       }

  23.           return 0;

  24. }


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;

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