欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【Linux】I/O多路复用—select和pselect

程序员文章站 2022-06-06 09:36:09
...

select函数

#include <sys/select.h>
int select(int maxfdp1, fd_set *restrict readfds, fd_set *restrict writefds,
            fd_set *restrict exceptfds, struct timeval *restrict tvptr);
        返回值:准备就绪的描述符数目;若超时,则返回0;若出错,返回-1

参数:

  • tvptr

    • tvptr == NULL
      永远等待。当所指定的描述符中有一个准备好或捕捉到一个信号则返回。如果捕捉到信号,则返回-1,errno置为EINTR。

    • tvptr->tv_sec == 0 && tvptr->tv_usec == 0
      根本不等待。测试所有指定的描述符并立即返回。

    • tvptr->tv_sec != 0 || tvptr->tv_usec != 0
      等待指定的秒数和微秒数。当有描述符准备好,或者当指定的时间值已超时则立即返回。如果超时,返回0。和第一种情况一样,这种等待会被信号中断。

  • readfds, writefds, exceptfds
    指向描述符集的指针,分别是我们关心的可读、可写或处于异常条件的描述符集合。每个描述符集存储在一个fd_set数据类型中。任意一个指针都可以为空。

  • fd_set类型
    这个类型由实现决定,它可以为每个描述符保持一位,我们可以把它看作一个很大的字节数组。
    对于该数据类型,只能进行如下处理:

    1. 分配一个该类型变量
    2. 将一个该类型变量赋值给另一该类型变量
    3. 对该类型变量使用如下四个函数:

      
      #include <sys/select.h>
      
      int FD_ISSET(int fd, fd_set *fdset);
                  返回值:fd在描述符集中,则返回非0值;否则,返回0
      int FD_CLR(int fd, fd_set *fdset); //清除一位
      int FD_SET(int fd, fd_set *fdset); //开启一位
      int FD_ZERO(fd_set *fd_set);    //将描述符集的所有位设置为0

      这些接口可实现为宏或者函数。在声明一个描述符集之后,必须用FD_ZERO将该描述符集清零,然后再设置我们关心的描述符的位。
      在select返回后,可使用FD_ISSET检查各描述符集中的指定位是否仍处于打开状态。

  • maxfdp1

    该参数的意思是”最大文件描述符编号加1“。考虑所有3个描述符集,其中最大的描述符编号加1,就是该参数的值。通过指定该位,内核只在指定范围内寻找大开的位,而不必关心三个描述符集中没有使用的那些位。因为描述符编号从0开始,所以要给最大描述符编号加1,实际上该参数是要检查的描述符数。

返回值:

  1. 返回-1表示出错,这是可能的。例如在有描述符准备好之前,捕捉到一个信号。此时一个描述符集都不会被修改。

  2. 返回0,表示没有描述符准备好。此时,所有描述符集都会被置0。

  3. 一个正的返回值表明已经准备好的描述符数。该值是3个描述符集中准备好的描述符数之和,如果一个描述符既准备好读又准备好写,则在返回值中会计数两次。这种情况下,3个描述符集中仍旧打开的位对应已准备好的描述符。

注意:

  1. 一个描述符阻塞与否不影响select是否阻塞。
  2. 如果在一个描述符上遇到了文件末尾,select认为它是可读的。也就是说,到达文件末尾时,select并不会给一个异常提示

pselect函数

#include <sys/select.h>
int pselect(int maxfdp1, fd_set *restrict readfds, fd_set *restrict writefds,
fd_set *restrict exceptfds, const struct timespec *restrict tsptr
const sigset_t *restrict sigmask);
        返回值:准备就绪的描述符数目;若超时,则返回0;若出错,返回-1

除下面几点外,pselect和select相同:

  1. pselect的超时值使用timespec结构,该结构以秒和纳秒表示超时值,能够提供更精确的超时时间。
  2. pselect的超时值被声明为const,这保证了超时值不会在调用时被修改。 pselect使用可选的信号屏蔽字。如果参数sigmask非空,则在函数被调用时,以原子的方式安装该屏蔽字,再返回时,恢复以前的屏蔽字。
相关标签: Linux select