POSIX部分写()

时间:2015-07-31 03:53:58

标签: c linux sockets posix

如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域套接字)。

然后,我有以下两个问题:

  • 部分()(或部分发送())是否可能发生在常规文件(或O_NONBLOCK 未设置的套接字)上?< / LI>
  • NONBLOCK套接字上的 writev ()和 sendmsg ()怎么样? 这非常重要,因为处理部分写入的向量(struct iovec [])有点麻烦。

抱歉英语不好。

3 个答案:

答案 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 [])有点麻烦。

更复杂的系统调用处理相同。在信号处理程序(如果有)返回后,用户空间库代码重新启动中断调用。