只是一些关于 I/O 多路复用的问题,我的教科书说:
select 函数会阻塞,直到读取集中的至少一个描述符准备好读取。当且仅当从该描述符读取 1 个字节的请求不会阻塞时,描述符 k 才准备好读取。
Q1-我不明白为什么从描述符中读取 1 个字节可能会阻塞?标准 IO 函数不是使用缓冲区吗?
Q2-为什么不直接 fork 一个子进程,让子进程去做可能会阻塞的工作?
Q3-如果我使用无缓冲系统调用 read() 从两个打开的文件中读取大量字节,所以它们都是阻塞的(需要很长时间),那么 select() 如何进行多路复用?
最佳答案
您误解了 select(2)手册页(另请参阅 select_tut(2) )。顺便说一句,你最好使用 poll(2)在新代码中,例如 this ;因为 select
限制(通过 fd_set
的大小)它可以使用的最高文件描述符(想想 C10K problem )。
select
手册页定义了一个 file descriptor你的process作为准备好 ...
... if it is possible to perform a corresponding I/O operation (e.g., read(2) without blocking, or a sufficiently small write(2)).
也就是说,如果一个文件描述符是这样的,你可以成功 read(2)至少一个字节,它是一个准备好的文件描述符(用于read
)。大多数时候,您将能够从中读取几个字节。您无法从中读取
的文件描述符,因为 read(2)尝试会阻塞,还没有准备好,因此可以称为阻塞的文件描述符。
有几种文件描述符被阻塞(即未就绪)的情况。常用的是某网socket(7)或一些 pipe(7) (或某些终端,请参阅 pty(7) 和 the TTY demystified 并注意 line discipline )没有更多输入。这就是为什么需要 poll
(或 select
、epoll(7) 等...)来编码 event loops。 (特别是在 widget toolkits 中用于 GUI,在 Web 服务器等中),因为你想避免忙 polling .
要进一步解释,请阅读一本不错的 Linux 编程书籍,例如 ALP .
您还可以阅读 Operating Systems: Three Easy Pieces获得更多关于操作系统的知识。
请注意 stdio(3)正在实现缓冲 IO(在 read(2) 和 write(2) 之上)。另见 fflush(3)和 setvbuf(3) .
另见 proc(5)以编程方式查询进程的状态(其中大部分是 idle 因为在 IO 操作或事件循环中被阻塞)。或者使用 ps(1) , top(1) (两者都在命令中使用 /proc/
)。
最后,查看许多free software的源代码项目(例如 Web 服务器、GUI 工具包等)。您可以找到许多使用 select
或 poll
的事件循环示例。
关于linux - 使用 select() 进行 I/O 多路复用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54085815/