zoukankan      html  css  js  c++  java
  • 驱动函数poll 和 应用里的 select


    阻塞操作是指,在执行设备操作时,若不能获得资源,则进程挂起直到满足可操作的条件再进行操作。非阻塞操作的进程在不能进行设备操作时,并不挂起。被挂起的进程进入sleep状态,被从调度器的运行队列移走,直到等待的条件被满足。


    select和poll的本质一样,前者在BSD Unix中引入,后者在System V中引入。poll和select用于查询设备的状态,以便用户程序获知是否能对设备进行非阻塞的访问,它们都需要设备驱动程序中的poll函数支持。

    驱动程序中poll函数中最主要用到的一个API是poll_wait,其原型如下:



    void poll_wait(struct file *filp, wait_queue_heat_t *queue, poll_table * wait);

      poll_wait函数 所做的工作是 把当前进程添加到wait参数指定的等待列表(poll_table)中。


    下面我们给globalvar的驱动添加一个poll函数:

    static unsigned int globalvar_poll(struct file *filp, poll_table *wait)
    {
     unsigned int mask = 0;

     poll_wait(filp, &outq, wait);

     //数据是否可获得? 
     if (flag != 0)
     {
      mask |= POLLIN | POLLRDNORM; //标示数据可获得
     }
     return mask;
    }

      需要说明的是,poll_wait函数并不阻塞,程序中poll_wait(filp, &outq, wait)这句话的意思并不是说一直等待outq信号量可获得,真正的阻塞动作是上层的select/poll函数中完成的。select/poll会在一个循环中对每个需要监听的设备调用它们自己的poll支持函数以使得当前进程被加入各个设备的等待列表。若当前没有任何被监听的设备就绪,则内核进行调度(调用schedule)让出cpu进入阻塞状态,schedule返回时将再次循环检测是否有操作可以进行,如此反复;否则,若有任意一个设备就绪,select/poll都立即返回。

     我们编写一个用户态应用程序来测试改写后的驱动。程序中要用到BSD Unix中引入的select函数,其原型为:

    int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

      其中readfds、writefds、exceptfds分别是被select()监视的读、写和异常处理的文件描述符集合,numfds的值是需要检查的号码最高的文件描述符加1。timeout参数是一个指向struct timeval类型的指针,它可以使select()在等待timeout时间后若没有文件描述符准备好则返回。struct timeval数据结构为: 

    struct timeval 

      int tv_sec; /* seconds */ 
      int tv_usec; /* microseconds */ 
    };

      除此之外,我们还将使用下列API:

      FD_ZERO(fd_set *set)――清除一个文件描述符集; 
      FD_SET(int fd,fd_set *set)――将一个文件描述符加入文件描述符集中; 
      FD_CLR(int fd,fd_set *set)――将一个文件描述符从文件描述符集中清除; 
      FD_ISSET(int fd,fd_set *set)――判断文件描述符是否被置位。

      下面的用户态测试程序等待/dev/globalvar可读,但是设置了5秒的等待超时,若超过5秒仍然没有数据可读,则输出"No data within 5 seconds":

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <stdio.h>
    #include <fcntl.h>
    #include <sys/time.h>
    #include <sys/types.h>
    #include <unistd.h>

    main()
    {
     int fd, num;
     fd_set rfds;
     struct timeval tv;

     fd = open("/dev/globalvar", O_RDWR, S_IRUSR | S_IWUSR);
     if (fd != - 1)
     {
      while (1)
      {
       //查看globalvar是否有输入
       FD_ZERO(&rfds);
       FD_SET(fd, &rfds);
       //设置超时时间为5s
       tv.tv_sec = 5;
       tv.tv_usec = 0;
       select(fd + 1, &rfds, NULL, NULL, &tv);

       //数据是否可获得?
       if (FD_ISSET(fd, &rfds))
       {
        read(fd, &num, sizeof(int));
        printf("The globalvar is %d ", num);

        //输入为0,退出
        if (num == 0)
        {
         close(fd);
         break;
        }
       }
       else
        printf("No data within 5 seconds. ");
      }
     }
     else
     {
      printf("device open failure ");
     }
    }








    http://blog.csdn.net/hanchaoman/article/details/7444337


    http://www.oschina.net/question/565065_67969












  • 相关阅读:
    IIS7报错:如果要使用托管的处理程序,请安装 ASP.NET
    mysql 存储过程 循环
    Mysql 遇到过的自带函数使用
    Mysql:is not allowed to connect to this MySQL server
    mysql 删除或更新时出现 you are usering safe update model 的解决方案
    将一个服务器的表数据插入到另一个服务器的表中
    C#操作Excel无法删除worksheet解决方案
    安装MongoDB数据库的注意事项
    Python爬取小猪短租,用的是lxml解析器
    使用Python爬取腾讯房产的新闻,用的Python库:requests 、re、time、BeautifulSoup ​​​​
  • 原文地址:https://www.cnblogs.com/liulaolaiu/p/11744645.html
Copyright © 2011-2022 走看看