函数select(UNIX环境高级编程笔记)

  I/O多路转接(I/O multiplexing)。为了事项I/O多路转接,先构造一张我们感兴趣的描述符(通常都不止一个)的列表,然后调用一个函数,知道这些描述符中一个已经准备好进行I/O时,该函数才返回、poll、pselect和select这3个函数使我们能够执行I/O多路转接。在从这些函数返回时,进程会被告知那些描述符已经准备好可以进行I/O。

函数select

  在所有POSIX兼容的平台上,select函数使我们可以执行多个I/O多路转接。传给select的参数告诉内核:
  ● 我们所关心的描述符;
  ● 对于 每个描述符我们所关心的条件。
  ● 愿意等待多上时间。
  从select返回时,内核告诉我们:
  ● 已准备好的描述符的总数量;
  ● 对于读、写或异常这3个条件中的每一个,哪些描述符已经准备好。

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

  中间3个参数readfds、writefds和exceptfds是指向描述符集的指针。每个描述符集存储在一个fd_set数据类型中。这个数据类型是由实现选择的,它可以为每一个可能的描述符保持一位。我们可以认为它只是一个很大的字节数组,如图所示:
函数select(UNIX环境高级编程笔记)

  对于fd_set数据类型,只可以进行以下处理:分配一个这种类型的变量,将这种类型的变量赋值给同类型的另一个变量,或者对这种类型的变量使用下列函数中的一个:

#include <sys/select.h>
int FD_ISSET(int fd, fd_set *set);
                返回值:若fd在描述符集中,返回非0值;否则,返回0
void FD_CLR(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);

  select的中间3个参数(指向描述符集的指针)中的任意一个都可以是空指针,这表示对相应条件并不关心。如果所有的3个指针都是NULL,则select提供了比sleep更精确的定时器。
  select的第一个参数maxfdp1的意思是“最大文件描述符编号值加1”。在3个描述符集中找出最大描述符值,然后加1,