如网络编程书籍中所述,select() 监视一组文件描述符以供读取。例如,下面是部分代码:
select(numfds, &read_fds, NULL, NULL, NULL);
这numfds
是 read_fds + 1 中的最大套接字数。这是否意味着每个“监视器”周期都会监视select()
从 0 到 numfds 的进程的所有文件描述符?我的意思是,如果我只有两个文件描述符要监视(0 和 26),那么 select 是否会监视从 0 到 26 的所有描述符?
如网络编程书籍中所述,select() 监视一组文件描述符以供读取。例如,下面是部分代码:
select(numfds, &read_fds, NULL, NULL, NULL);
这numfds
是 read_fds + 1 中的最大套接字数。这是否意味着每个“监视器”周期都会监视select()
从 0 到 numfds 的进程的所有文件描述符?我的意思是,如果我只有两个文件描述符要监视(0 和 26),那么 select 是否会监视从 0 到 26 的所有描述符?
select
readfds
根据您传入的 fd 集 ( , writefds
, )选择要观看的 fd exceptfds
。这些集合通常被实现为位向量,因此select
将扫描向量以查看选择了哪些 fd。作为一种优化,您传入要扫描的 fd 的数量,这样select
就不必查看所有 fd FD_SETSIZE
(在编译单元之间甚至可能不一样)。
select
是一个相当昂贵的调用,因为每次调用select
. 在许多平台上,select
它只是在系统调用之上实现poll
,它为等待文件描述符提供了更有效的接口。
每个监视器周期意味着,只要操作系统基本上处理它,它可能会选择定期检查描述符或通过事件或中断处理它。当在套接字文件描述符上接收到数据时,描述符文件将被数据填充,并通知正在等待它的进程。这并不总是立即发生,因为进程不会立即被唤醒,它只是简单地放回准备运行队列(因为它被 select 调用阻塞)。如果 select 调用碰巧失败(超时未收到数据),则计时器将触发并将进程放回运行队列。
FD_SET
是的,检查或监视 0-26 中的 fd 。这只是为搜索文件描述符设置上限。IIRC 这是因为fd_set
类型在内部实现为位集,因为指定索引更容易,因为这样可以节省空间。我在前面的陈述中可能是错的,因为我有一段时间没有访问 glibc 中的代码了。