首先,一些预备:
使用
O_NONBLOCK和
poll()是常见做法-并非相反。要顺利进行,您需要确保处理所有
poll()和
read()正确的返回状态:
read()``0
均值EOF的返回值-另一端已关闭其连接。(通常,但不是在所有 *** 作系统上)这对应于poll()
返回POLLHUP
清除。您可能想POLLHUP
在尝试之前进行检查read()
,但这并不是绝对必要的,因为read()
可以保证0
在书写侧关闭后返回。- 如您所知
read()
,如果您在作家连接之前打电话,并且您有O_RDonLY | O_NONBLOCK
,您将反复得到EOF(read()
返回0
)。但是,如果您习惯在调用之前poll()
等待POLLIN
事件read()
,它将等待编写器连接,而不产生EOF。 read()
返回值-1
通常表示错误。但是,如果是errno == EAGAIN
,这仅表示当前没有更多数据可用,并且您没有阻塞,因此可以返回到poll()
其他设备需要处理的情况。如果errno == EINTR
,则read()
在读取任何数据之前已中断,您可以返回poll()
或直接read()
再次调用。
现在,对于Linux:
如果您使用来打开阅读侧
O_RDONLY
,则:- 在
open()
将阻塞,直到有相应的作家开放。 poll()
将给予POLLIN
当数据准备好被读取,或出现EOF时r事件。read()
将一直阻塞,直到读取请求的字节数,关闭连接(返回0),被信号中断或发生致命的IO错误为止。这种阻碍性的破坏了使用的目的poll()
,这就是为什么poll()
几乎总是与一起使用的原因O_NONBLOCK
。您可以使用an 在超时后alarm()
唤醒read()
,但这太复杂了。- 如果作家关闭,然后将读卡器将获得
poll()
POLLHUP
r事件和read()
将返回0
之后下去。此时,读取器必须关闭其文件句柄并重新打开它。
- 在
如果您使用来打开阅读侧
O_RDonLY | O_NONBLOCK
,则:- 该
open()
不会阻止。 poll()
将给予POLLIN
当数据准备好被读取,或出现EOF时r事件。poll()
也会阻塞,直到没有可用的编写器为止。- 读取所有当前可用的数据之后,如果连接仍处于打开状态,
read()
则将返回-1并进行设置errno == EAGAIN
,或者0
如果连接器已关闭(EOF) 或尚未由写入器打开 ,则将返回-1 。如果为errno == EAGAIN
,则意味着该返回到了poll()
,因为该连接已打开但没有更多数据。当时errno == EINTR
,read()
尚未读取任何字节并被信号中断,因此可以重新启动它。 - 如果作家关闭,然后将读卡器将获得
poll()
POLLHUP
r事件,并且read()
将返回0
之后下去。此时,阅读器必须关闭其文件句柄并重新打开它。
- 该
(特定于Linux :)如果您在阅读方面打开
O_RDWR
,则:- 该
open()
不会阻止。 poll()
将给予POLLIN
当数据准备好被读取r事件。但是,对于命名管道,EOF不会引起POLLIN
或POLLHUP
阻止。read()
将一直阻塞,直到读取请求的字节数,被信号中断或发生其他严重的IO错误为止。对于命名管道,它不会返回errno == EAGAIN
,甚至不会0
在EOF上返回。它会一直坐在那里,直到读取了请求的确切字节数,或者直到接收到一个信号为止(在这种情况下,它将返回到目前为止已读取的字节数,或者errno == EINTR
如果没有读取到字节,则返回-1并进行设置)。 。- 如果编写器关闭,则在另一个编写器打开命名管道的情况下,读取器也不会失去稍后读取命名管道的功能,但是读取器也不会收到任何通知。
- 该
(特定于Linux :)如果您在阅读方面打开
O_RDWR | O_NONBLOCK
,则:- 该
open()
不会阻止。 poll()
将给予POLLIN
当数据准备好被读取r事件。但是,EOF不会导致POLLIN
或限制POLLHUP
命名管道。- 读取所有当前可用数据后,
read()
将返回-1
并设置errno == EAGAIN
。现在该返回到poll()
等待更多数据(可能来自其他流)的时间。 - 如果编写器关闭,则在另一个编写器打开命名管道的情况下,读取器也不会失去稍后读取命名管道的功能。连接是持久的。
- 该
如您所知,
O_RDWR与管道一起使用不是POSIX或其他标准。
然而,由于这个问题似乎来了的时候,在Linux上的最佳途径,使“d性命名管道”的生存,即使一方关闭,并不会引起
POLLHUPrevents中或回报
0的
read(),就是用
O_RDWR| O_NONBLOCK。
我看到了在Linux上处理命名管道的三种主要方法:
(便携式。)不使用
poll()
,并且使用单个管道:open(pipe, O_RDONLY);
- 主循环:
read()
根据需要提供尽可能多的数据,可能会在read()
调用时循环。- 如果
read() == -1
和errno == EINTR
,则read()
重新遍历。 - 如果为
read() == 0
,则连接已关闭,并且已接收所有数据。
- 如果
(可移植。)使用
poll()
,并期望管道(即使是命名管道)仅打开一次,并且一旦关闭,则读取器和写入器都必须重新打开它们,从而建立新的管道:open(pipe, O_RDonLY | O_NONBLOCK);
- 主循环:
poll()
对于POLLIN
事件,可能一次在多个管道上。(注意:这可以防止read()
在连接编写器之前获得多个EOF。)read()
根据需要提供尽可能多的数据,可能会在read()
调用时循环。- 如果
read() == -1
和errno == EAGAIN
,请返回poll()
步骤。 - 如果
read() == -1
和errno == EINTR
,则read()
重新遍历。 - 如果为
read() == 0
,则连接已关闭,您必须终止,或者关闭并重新打开管道。
- 如果
(不可移植,特定于Linux。)使用
poll()
,并期望命名管道永远不会终止,并且可以多次连接和断开连接:open(pipe, O_RDWR | O_NONBLOCK);
- 主循环:
poll()
对于POLLIN
事件,可能一次在多个管道上。read()
根据需要提供尽可能多的数据,可能会在read()
调用时循环。- 如果
read() == -1
和errno == EAGAIN
,请返回poll()
步骤。 - 如果
read() == -1
和errno == EINTR
,则read()
重新遍历。 - 如果
read() == 0
,那是错误的-不应O_RDWR
在命名管道上发生,而应该在O_RDONLY
未命名管道上发生;它表示已关闭的管道,必须将其关闭并重新打开。如果您在同一poll()
事件处理循环中混合使用命名管道和未命名管道,则可能仍需要处理这种情况。
- 如果
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)