write()系统调用何时写入所有请求的缓冲区而不是仅执行部分写入?

Chr*_*kle 6 unix linux

如果我指望我的write()系统调用写入例如100字节,我总是将该write()调用放在一个循环中,该循环检查返回的长度是否是我预期发送的长度,如果不是,它会缓冲缓冲区指针并减少写入量的长度.

所以我再次这样做了,但是现在有了StackOverflow,我可以问你们所有人是否知道我的写作时间会写出我要求的所有内容而不是给我一个部分写入?

附加评论:X-Istence的回复提醒我,我应该注意到文件描述符是阻塞的(即,不是非阻塞).我认为他建议阻塞文件描述符上的write()不会写入所有指定数据的唯一方法是write()被信号中断.这似乎至少对我有直观的意义......

Art*_*yom 5

write可能会返回部分写入,尤其是使用套接字上的操作或内部缓冲区已满.这么好的方法是做以下事情:

while(size > 0 && (res=write(fd,buff,size))!=size) {
    if(res<0 && errno==EINTR) 
       continue;
    if(res < 0) {
        // real error processing
        break;
    }
    size-=res;
    buf+=res;
}
Run Code Online (Sandbox Code Playgroud)

永远不要接受通常发生的事情......

注意:如果是完整磁盘,您将获得ENOSPC而不是部分写入.


X-I*_*nce 4

您需要检查 errno 以查看您的调用是否被中断,或者为什么 write() 提前返回,以及为什么它只写入了一定数量的字节。

man 2 写

当在受流量控制的对象(例如套接字)上使用非阻塞 I/O 时,write() 和 writev() 写入的字节数可能会少于请求的字节数;必须记录返回值,并且应尽可能重试其余操作。

基本上,除非您正在写入非阻塞套接字,否则唯一会发生这种情况的情况是您被信号中断。

[EINTR] 在写入完成之前,信号中断了写入。

有关可以返回什么以及何时返回的更多信息,请参阅手册页中的“错误”部分。从那里您需要确定错误是否严重到足以记录错误并退出,或者您是否可以继续手头的操作!

这在Marc J. Rochkind 的《高级 Unix 编程》一书中都有讨论,我在这本书的帮助下编写了无数的程序,并且在为类似 UNIX 的操作系统编程时建议使用它。