如SUSv4或POSIX.1-2008中所述
http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html#tag_16_685_08
如果写()到NONBLOCK 管道/ FIFO ,则write()调用可能返回小于 nbytes 的值。
因此,有必要检查返回值,并在下面演示的循环中写()缓冲区的其余部分:
while (bytes_to_write > 0) {
select(...); // Or poll()
retv = write(...);
if (retv < 0)
... // Error
bytes_to_write -= retv;
}
该标准没有提及常规文件,特殊文件(又称设备)和套接字,尤其是基于流的套接字(例如,TCP套接字和UNIX域套接字)。
然后,我有以下两个问题:
抱歉英语不好。
答案 0 :(得分:3)
确定。由于标准没有提供任何保证,我们不能假设完整write()
。
我用Google搜索了部分写 v 并得到了答案:
http://developerweb.net/viewtopic.php?id=4154
是的,我之前也见过这种行为(尽管如此,使用sendmsg()及其iovecs)...... 实际上,不,它不是不正确/意外的行为...... read()/ recv()和write()/ send()(以及I / O函数的所有排列)都可以返回短读/写,所有套接字代码需要准备好处理...如果是没关系 它们是阻塞或非阻塞模式套接字,或者......所有这些控制都是什么 当缓冲区完全为空(在输入的情况下)或完全填满(在 输出的情况)...但是,当发送缓冲区不是很满时,任何写入它(通过一个 阻塞或非阻塞套接字)超过剩余的可用空间量 尽可能多地写,然后返回短写入次数...而且,你是 期待再次处理,再发送剩余金额......正常 write()/ send(),这很容易做到,但是使用writev()/ sendmsg()iovecs,它确实成了 难以处理,真正的痛苦......但是,你仍然必须这样做
writev_all()
是无法避免的。
感谢。
答案 1 :(得分:-1)
部分write()(或部分send())可能会出现在常规文件
上
是
(或未设置O_NONBLOCK的套接字)?
是
NONBLOCK套接字上的writev()和sendmsg()怎么样?
是
这非常重要,因为处理部分写入的向量(struct iovec [])有点麻烦。
不是真的。你知道写了多少字节,你只需要推进指针并相应地减小大小。如果对你来说太麻烦,请使用阻止模式。
答案 2 :(得分:-1)
部分
write()
(或部分send()
)可能会出现在常规文件(或未设置O_NONBLOCK
的套接字)上吗?
可能。信号可以中断任何I / O操作,但库将根据SA_RESTART
标志自动重启:
此标志影响可中断功能的行为;也就是说,指定为
errno
设置为[EINTR]时失败的那些。如果设置,并且该信号中断了指定为可中断的功能,则该功能应重新启动,除非另有说明,否则不应使用[EINTR]失败。如果重新启动使用超时的可中断功能,则重新启动后超时的持续时间将设置为未指定的值,该值不会超过原始超时值。如果未设置该标志,则此信号中断的可中断函数将失败,errno
设置为[EINTR]。
此标志在Linux上默认设置,因此除非自定义信号处理生效,否则您无需担心。
writev()
套接字sendmsg()
和NONBLOCK
怎么样?这非常重要,因为处理部分写入的向量(struct iovec []
)有点麻烦。
更复杂的系统调用处理相同。在信号处理程序(如果有)返回后,用户空间库代码重新启动中断调用。