select() 函数允许我们在一组文件描述符上进行 I/O 多路复用。相关原型及相关操作宏定义如下:
[C++] 纯文本查看 复制代码 #include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
/*返回:就绪的文件描述符数量,在超时的情况下返回 0,在产生错误时返回 -1 */
void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);
/*返回:如果在 fdset 中设置 fd,则返回非零值,否则返回 0*/
select() 函数用于在大量文件描述符上执行同步的、多路复用的 I/O 。
nfsd 参数确定测试的文件描述符的范围,该范围为 0 到 nfds-1 。可以自己确定用于 nfds 的值,或者可以使用在 <sys/select.h> 中定义的 FD_SETSIZE 常量 (当包含 <sys/types.h> 时自动包含)。32位进程的默认 FD_SETSIZE 是 1024,但通过在包含系统提供的任何头文件之前为其定义较大的数值,可以在编译时增加该值。支持最大 FD_SETSIZE 为 65535,这是 64 位进程的默认值。不必要的检查这个较大数量的描述符会浪费 CPU 时间,因此相比于使用 FD_SETSIZE,优先选择为 nfds 提供自己的值 ---- 如果确实为nfds 提供自己的值,必须确保这个值不会超出 FD_SETSIZE .
每个 readfds ,writefds 和 errorfds 参数指向一个文件描述符集。这些描述符集告诉 select() 函数针对每个文件描述符感兴趣的事件;readfs 是有兴趣从中读取的描述符列表,writefds 是有兴趣写入其中的描述符集,errorfds 是有兴趣从中接收一场条件的描述符列表。
任何这些指针可能都是 NULL ( 指出我们对参与该参数关联的任何事件都不感兴趣 );如果它们不是 NULL ,它们指向 fd_set 数据类型。fd_set 是不透明的数据类型,可以将其认为是位的数组:每一位对应每个文件描述符。更详细的 fd_set 类型说明见:http://www.groad.net/bbs/read.php?tid=1063
操作 fd_set 的唯一方法 ( 除了声明变量或将一个 fd_set 赋予另一个 )是使用下面 4 个宏中的一个:
FD_ZERO 该宏清除由 fdset 指向的描述符集中的所有位。一旦已经声明了一个描述符集,必须使用这个宏清除它。 FD_SET 该宏启用 (设置) 由 fdset 指向的描述符集中 fd 的位。 FD_CLR 该宏关闭 (清除) 由 fdset 指向的描述符集中 fd 的位。 FD_ISSET 可以使用这个宏来确定是否设置了由 fdset 指向的描述符集中 fd 的位。 在每次调用 select() 函数前,必须重新初始化 readfds, writefds 和 errorfds 参数。
关于上面宏的解析参考:http://www.groad.net/bbs/read.php?tid=3297
使用宏 FD_ZERO, FD_SET, FD_ISSET 宏的普通示例:
[C++] 纯文本查看 复制代码 #include <stdio.h>
#include <string.h>
#include <sys/types.h>
int main(void)
{
fd_set read_set;
fd_set write_set;
int i;
FD_ZERO (&read_set);
FD_ZERO (&write_set);
FD_SET (0, &read_set);
FD_SET (1, &write_set);
FD_SET (2, &read_set);
FD_SET (3, &write_set);
printf ("read_set:\n");
for (i = 0; i < 4; i++) {
printf (" bit %d is %s\n", i, (FD_ISSET (i, &read_set) ? "set" : "clear"));
}
printf ("write_set:\n");
for (i = 0; i < 4; i++) {
printf (" bit %d is %s\n", i, (FD_ISSET (i, &write_set) ? "set" : "clear"));
}
return (0);
}
运行及输出:beyes@linux-beyes:~/C/base> ./select.exe
read_set:
bit 0 is set
bit 1 is clear
bit 2 is set
bit 3 is clear
write_set:
bit 0 is clear
bit 1 is set
bit 2 is clear
bit 3 is set |