我知道 select 在返回时修改输入集。但如何呢? 输入集中的 fd 如何变得不在输入集中?在我看来,只要 fd 一开始就在输入集中,fd_isset(fd) 就会返回 true。那么 select() 到底是如何修改其输入集的呢?
这是fd_set结构:
typedef struct fd_set {
u_int fd_count;
SOCKET fd_array[FD_SETSIZE];
} fd_set;
那么 select() 会更新哪些字段呢?我们仍然想跟踪所有的 fd,所以我不明白 select() 更改 fd_count 或 fd_array 有什么意义?那么,select() 改变了什么?
来自手册页:
“退出时,这些集合会被就地修改以指示哪些文件描述符实际更改了状态。”
但是关于该系列的哪些方面进行了修改的详细信息明显缺失。
编辑: 针对答案: 那么以下是正确的使用方法吗?
while (not error and not socket closes){
FD_ZERO(&readSet);
FD_ZERO(&writeSet);
FD_SET(fd, &readSet);
FD_SET(socket_num, &readSet);
FD_SET(fd, &writeSet);
FD_SET(socket_num, &writeSet);
select(nfds, &readSet, writeSet, NULL, NULL);
if(FD_ISSET(fd, &readSet)){
read(fd, buf, sizeof(buf));
write(socket_num, buf, sizeof(buf));
/*memset(buf, 0, sizeof(buf));*/
}
if(FD_ISSET(socket_num, &readSet)){
read(socket_num, buf, sizeof(buf));
write(fd, buf, sizeof(buf));
}
}
输入时,
fd_set
告诉 select()
应该检查哪些 FD。 select
制作此列表的副本以供内部使用。当它返回时,它会修改输入结构以包含返回的信息。它可以修改 fd_count
和 fd_array
。
这就是为什么使用
select()
的循环通常会在循环之前保存 fd_set
的副本,并将其复制回每次循环中 select()
调用中使用的变量,例如
FD_SET(sockfd, &fd_set_init);
while(true) {
FD_COPY(&fd_set_init, &fd_set);
n = select(nfds, &fd_set, NULL, NULL, NULL);
if (n > 0) {
// Use fd_set here
}
}
select()
函数将指针指向其参数中的各种文件描述符集。它可以通过这些指针修改 FD 集,就像任何函数可以修改传递给它的任何指针的指示对象一样。鉴于您提供的 fd_set
定义,它可能会通过写入 fd_array
成员 [更新:] 的适当元素来实现,也可能写入 fd_count
成员。
但请注意,说您提供的结构定义是 the
fd_set
结构是不正确的。假设您从与您相关的头文件中提取了它,因此它是 an fd_set
结构,但结构定义没有记录,因此它在其他系统上的实现可能有所不同。这就是提供 FD_*()
函数来操作这些结构内容的原因之一。
与您的问题特别相关,您可以在
FD_ISSET()
返回后使用 select()
测试文件描述符集的内容。