POSIX部分写入()

如SUSv4或POSIX.1-2008中所述
http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html#tag_16_685_08
如果将write () 写入 NONBLOCK pipe道/ FIFO ,则write()调用可能会返回小于nbytes的值。 因此,有必要检查返回值,并在下面显示的循环中写入 ()缓冲区的其余部分:

while (bytes_to_write > 0) { select(...); // Or poll() retv = write(...); if (retv < 0) ... // Error bytes_to_write -= retv; } 

标准中没有提到常规文件,特殊文件(又称设备)和套接字 ,特别是基于stream的套接字(例如,TCP套接字和UNIX域的套接字)。

那么,我有以下两个问题:

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

对不起,英文不好。

好。 由于标准没有提供任何保证,我们不能完全write()

我用Google搜索了部分代码并得到了一个答案:

http://developerweb.net/viewtopic.php?id=4154

是的,我之前也看到过这种行为(尽管用sendmsg()和它的iovecs)…实际上,它不是不正确/意外的行为… read()/ recv()和write )/ send()(以及I / O funcs的所有排列)可以返回短读/写,并且所有套接字代码都需要准备好处理这些…无论它们是阻塞的还是非阻塞的 – 阻塞模式套接字,要么…所有的控制是当缓冲区是完全空的时候(在输入的情况下)或者完全满的时候(在输出的情况下)…但是,当发送缓冲区不是相当完整,任何写入(通过一个阻塞或非阻塞的插座)超过剩余空间的数量将尽可能多地写入,然后返回短的写入计数…而且,您预计处理再次调用它,发送剩余的数量…与正常的write()/ send(),这很容易做到,但与writev()/ sendmsg()iovecs,它确实变得棘手的处理,真正的痛苦…但是,你仍然必须这样做

writev_all()不能避免。

谢谢。

将部分write() (或部分send() )可能发生在常规文件(或O_NONBLOCK设置的套接字)?

有可能。 信号可以中断任何I / O操作,但是库会根据SA_RESTART标志自动重启:

该标志影响可中断功能的行为; 也就是说,指定的errno设置为[EINTR]失败。 如果被设置,并且指定为可中断的功能被该信号中断,则除非另外指定,否则该功能将重新启动并且不会因为[EINTR]而失效。 如果重新启动使用超时的可中断功能,则重新启动后超时的持续时间将设置为未超出原始超时值的未指定值。 如果没有设置标志,由此信号中断的可中断功能将失败,并将errno设置为[EINTR]。

这个标志在Linux上是默认设置的,所以你不必担心,除非自定义的信号处理有效。

如何在NONBLOCK套接字writev()sendmsg() ? 这是非常重要的,因为处理部分写入的向量( struct iovec [] )有点麻烦。

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

部分写入()(或部分发送())可能发生在常规文件上

是。

(或套接字O_NONBLOCK未设置)?

是。

如何在NONBLOCK套接字writev()和sendmsg()?

是。

这是非常重要的,因为处理部分写入的向量(struct iovec [])有点麻烦。

不是真的。 你知道有多少字节被写入,你只需要提前指针并相应地减小大小。 如果对您来说太麻烦了,请使用阻止模式。