select()中的描述符位设置

时间:2018-02-03 06:47:59

标签: linux select io network-programming multiplexing

我目前正在研究用于网络编程中I / O复用的select()。 select接受以下参数:

  

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

select()调用的fd_set数据类型的描述如下:

  

select使用描述符集,通常是整数数组   对应于描述符的每个整数中的位。例如,使用   32位整数,数组的第一个元素对应   描述符0到31,数组的第二个元素对应   描述符32到63,等等。

如果是这种情况那么根据我的理解,如果你有读取集的描述符1,4,5那么该值将设置为:

LSB                          MSB   

01001100000000000000000000000000    // descriptor bits set corresponding to 1,4,5

0123456........................31  //descriptor bit positions

0-31位将形成整数值为50,这应该是读取集的第一个元素,即数组表示法中的[50],因为fd_set数据类型为:

typedef struct fd_set {
  u_int  fd_count;
  SOCKET fd_array[FD_SETSIZE];
} fd_set;  

但是当我检查了strace -p 2172,其中2172是我输入ls命令的另一个终端的pid时,它显示结果为:

pselect6(1,[0],NULL,NULL,NULL,{[],8})

为什么读取pselect6数组中的描述符集:[0],当与标准输入相关的fd描述符为0时,整数值变为1,即[1]?如果我没有正确解释说明,请告诉我。

此外,如果设置了读取和异常集,并且在调用select期间会发生什么,只有读取集中的描述符已准备好进行读取操作并返回。但是,稍后对异常集的描述符也准备好但是因为select已经返回,所以检查FD_ISSET(int fd,fd_set * exceptSet)会返回什么?

请帮助我,因为我是网络编程的新手。

1 个答案:

答案 0 :(得分:1)

strace未显示fd_set中的实际二进制值。它正在将其转换为与之对应的FD编号列表。因此,如果二进制值为01001100000000000000000000000000,则会显示[1,4,5]

fd_set的内部实现依赖于实现,您无需关心它。您只需使用<select.h>中的宏来设置,清除和测试集合中的描述符。