首页 > 解决方案 > POSIX 部分 write() 和信号中断

问题描述

从手册页write()

请注意,成功的 write() 可能传输少于 count 个字节。这种部分写入可能由于各种原因而发生;例如,因为磁盘设备上没有足够的空间来写入所有请求的字节,或者因为阻塞的 write() 到套接字、管道或类似的东西在传输一些字节之后被信号处理程序中断,但在它之前已传输所有请求的字节。在部分写入的情况下,调用者可以进行另一个 write() 调用以传输剩余的字节。随后的调用将传输更多字节或可能导致错误(例如,如果磁盘现在已满)。

我有以下问题

1) 在write()部分传输后被信号处理程序中断的情况下,write() 将设置errnoEINTR?

2)如果errno没有设置,有没有办法在没有额外代码的情况下识别这样的事件(比如安装信号配置并将标志值设置为true)?

注意:在信号中断事件发生后,进一步的write()调用成功地传输了剩余的字节。

标签: clinuxnetwork-programmingposix

解决方案


要回答您的个人编号问题:

  1. errno仅在其中一个标准函数返回一个指示错误的值之后才有意义 - for write, -1 - 并且在任何其他可能破坏它的标准函数或应用程序代码被调用之前。所以不,如果write返回一个短写,errno将不会被设置为任何有意义的东西。如果它等于EINTR,它恰好是;这不是您可以解释的有意义的事情。

  2. 识别此类事件的方法是返回值严格小于nbytes参数。这实际上并没有告诉你短写的原因,所以它可能是其他的东西,比如空间不足。如果您需要知道,您需要安排信号处理程序通知您。但在几乎所有情况下,您实际上并不需要知道。

关于注释,如果在信号到达后write返回完整nbytes,则信号处理程序是非中断的。这是 Linux 上任何现代 libc(glibc、musl,基本上除了 libc5 之外的任何东西)的默认设置,而且它几乎总是正确的。如果您确实想要中断信号,则必须安装信号处理程序sigactionSA_RESTART清除标志。(相反,如果您要安装信号处理程序,则希望具有正常、合理、不中断的行为,为了可移植性,您应该使用sigaction并设置SA_RESTART标志而不是使用旧功能signal)。


推荐阅读