检查使用非阻塞打开时所有数据是否发送完毕

0 投票
6 回答
942 浏览
提问于 2025-04-16 04:59

如果我用 os.open( '/dev/ttyS2', O_RDWR | O_NDELAY ) 这个命令打开一个文件,有没有办法检查我的 'write()' 命令什么时候完成?或者,我能不能打开一个文件,让读取操作不阻塞,但写入操作是阻塞的?

6 个回答

1

O_NDELAY这个标志会同时影响读取和写入操作。如果你想在一个非阻塞的文件上进行阻塞写入,可以使用选择(Python模块)来监控这个文件,然后在它变得可以写入的时候进行写入,通常是在一个循环中进行。

3

如果你在写入一个终端(就像你在例子中做的那样),你可以使用 termios.tcdrain 来等待所有写入的字节都被发送出去。

你的 write 系统调用仍然是非阻塞的,这意味着它不会一直等着完成,所以你需要处理 EWOULDBLOCKEAGAIN 这些错误。同时,你可以使用 select(2)poll(2)epoll(7) 来判断什么时候可以向文件描述符写入数据。这些工具都是为了和非阻塞的文件描述符一起使用的。

4

你对“非阻塞”的理解有些误区。它并不意味着异步操作——你可以有异步/同步和阻塞/非阻塞的任意组合。

一个 write() 操作只是把数据交给内核去处理。当 write() 成功返回时,内核已经处理了这些数据——这和文件描述符是阻塞还是非阻塞没有关系。此时内核是否真的完成了写入是另外一回事(通常答案是“没有”——大多数文件描述符都是异步的)。

如果内核没有足够的空间来缓存你想写入的数据,write() 就无法完成,这就是非阻塞和阻塞的区别所在——在阻塞的情况下,write() 会一直等到有空间可用。而在非阻塞的情况下,write() 会返回一个错误(EAGAIN),这时就得由你自己决定什么时候重试。

如果你想等到所有写入终端设备的数据实际上都已经发送到硬件,可以使用 tcdrain()——但这通常是没必要的。或者,如果你希望 write() 在数据被内核接受之前一直阻塞,你可以使用 fcntl() 临时将文件描述符设置为阻塞模式。

撰写回答