zoukankan      html  css  js  c++  java
  • Linux下select和poll的用法


    转载自:http://blog.csdn.net/dingyuanpu/article/details/5572352

    select()函数的作用

        系统调用select和poll的后端实现,用这两个系统调用来查询设备是否可读写,或是否处于某种状态。如果poll为空,则驱动设备会被认为即可读又可写,返回值是一个状态掩码
    如何使用select()函数?
        select()函数的接口主要是建立在一种叫'fd_set'类型的基础上。它('fd_set') 是一组文件描述符(fd)的集合。由于fd_set类型的长度在不同平台上不同,因此应该用一组标准的宏定义来处理此类变量:

        fd_set set;
        FD_ZERO(&set);      
        FD_SET(fd, &set);   
        FD_CLR(fd, &set);   
        FD_ISSET(fd, &set); 
         
    在过去,一个fd_set通常只能包含少于等于32个文件描述符,因为fd_set其实只用了一个int的比特矢量来实现,在大多数情况下,检查 fd_set能包括任意值的文件描述符是系统的责任,但确定你的fd_set到底能放多少有时你应该检查/修改宏FD_SETSIZE的值。*这个值是系统相关的*,同时检查你的系统中的select() 的man手册。有一些系统对多于1024个文件描述符的支持有问题。[译者注: Linux就是这样的系统!你会发现sizeof(fd_set)的结果是128(*8 = FD_SETSIZE=1024) 尽管很少你会遇到这种情况。]

    select的基本接口十分简单:

        int select(int nfds, fd_set *readset, fd_set *writeset,

                   fd_set *exceptset, struct timeval *timeout); 
    其中:


    nfds    
         需要检查的文件描述符个数,数值应该比是三组fd_set中最大数
         更大,而不是实际文件描述符的总数。
    readset   
         用来检查可读性的一组文件描述符。
    writeset
         用来检查可写性的一组文件描述符。
    exceptset
         用来检查意外状态的文件描述符。(注:错误并不是意外状态)
    timeout
         NULL指针代表无限等待,否则是指向timeval结构的指针,代表最
         长等待时间。(如果其中tv_sec和tv_usec都等于0, 则文件描述符
         的状态不被影响,但函数并不挂起)
         
    函数将返回响应操作的对应操作文件描述符的总数,且三组数据均在恰当位置被修改,只有响应操作的那一些没有修改。接着应该用FD_ISSET宏来查找返回的文件描述符组。

    这里是一个简单的测试单个文件描述符可读性的例子:

         int isready(int fd)
         {
             int rc;
             fd_set fds;
             struct timeval tv;
       
             FD_ZERO(&fds);
             FD_SET(fd,&fds);
            //tv.tv_sec = tv.tv_usec = 0;
       
            //rc = select(fd+1, &fds, NULL, NULL, &tv);
             rc = select(fd+1, &fds, NULL, NULL, NULL);
             if (rc < 0)
               return -1;
       
             return FD_ISSET(fd,&fds) ? 1 : 0;
          }
         
    当然如果我们把NULL指针作为fd_set传入的话,这就表示我们对这种操作的发生不感兴趣,但select() 还是会等待直到其发生或者超过等待时间。

    [译者注:在Linux中,timeout指的是程序在非sleep状态中度过的时间,而不是实际上过去的时间,这就会引起和非Linux平台移植上的时间不等问题。移植问题还包括在System V风格中select()在函数退出前会把timeout设为未定义的 NULL状态,而在BSD中则不是这样, Linux在这点上遵从System V,因此在重复利用timeout指针问题上也应该注意]


    Linux

    下select调用的过程:
    1.用户层应用程序调用select(),底层调用poll())
    2.核心层调用sys_select() ------> do_select()
      最终调用文件描述符fd对应的struct file类型变量的struct file_operations *f_op的poll函数。
      poll指向的函数返回当前可否读写的信息。
      1)如果当前可读写,返回读写信息。
      2)如果当前不可读写,则阻塞进程,并等待驱动程序唤醒,重新调用poll函数,或超时返回。
    3.驱动需要实现poll函数。
      当驱动发现有数据可以读写时,通知核心层,核心层重新调用poll指向的函数查询信息。
      poll_wait(filp,&wait_q,wait)    // 此处将当前进程加入到等待队列中,但并不阻塞
      在中断中使用wake_up_interruptible(&wait_q)唤醒等待队列

  • 相关阅读:
    Azure 虚拟机安全加固整理
    AzureARM 使用 powershell 扩容系统磁盘大小
    Azure Linux 云主机使用Root超级用户登录
    Open edX 配置 O365 SMTP
    powershell 根据错误GUID查寻错误详情
    azure 创建redhat镜像帮助
    Azure Powershell blob中指定的vhd创建虚拟机
    Azure Powershell 获取可用镜像 PublisherName,Offer,Skus,Version
    Power BI 连接到 Azure 账单,自动生成报表,可刷新
    Azure powershell 获取 vmSize 可用列表的命令
  • 原文地址:https://www.cnblogs.com/techstone/p/3321352.html
Copyright © 2011-2022 走看看