我目前正在研究用于网络编程中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)会返回什么?
请帮助我,因为我是网络编程的新手。
答案 0 :(得分:1)
strace
未显示fd_set
中的实际二进制值。它正在将其转换为与之对应的FD编号列表。因此,如果二进制值为01001100000000000000000000000000
,则会显示[1,4,5]
。
fd_set
的内部实现依赖于实现,您无需关心它。您只需使用<select.h>
中的宏来设置,清除和测试集合中的描述符。