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