为什么连续写入会在缓冲区中保留4K字节?


30

我基本上有以下代码:

int fileWrite(int file, void * pBuffer, size_t size)
{
    size_t bytesWritten = (size_t)write( file, pBuffer, size ) ;
    if (bytesWritten != size)
    {
       return -1;
    }
    return 0;
}

如果大小为1GB,则可以使用,但是当大小为〜2GB时,则可以连续保留4K字节。我可以通过将写操作包装在循环中并向上移动缓冲区来解决此问题,但是我很好奇为什么它总是失败。

例如,如果大小为2147483648,则只写2147479552,而使4096不写。为什么会发生这种情况,并且总是将写操作包装在循环中是否正确?


2
您是否以32位模式运行它?2gig是最大的32位数字。
Barmar

2
write一次要消耗多少数据的规则取决于数据接收器的类型file(例如“常规”文件,管道,流套接字,数据报套接字等)。你可以说得更详细点吗?
zwol

7
等一下,您要write一次尝试整个文件吗?通常的方法是一次以缓冲区大小流式传输数据,直到您编写所有内容为止。
a安

4
@Luaan如果你已经把所有我看不出有什么数据一次,但因为这问题和答案写说明这一切,write()并没有写这一切(这也适用于小的缓冲区太)

8
无论有什么SSIZE_MAX限制,“我都可以通过将写操作包装在循环中来解决此问题” 。该write()规范说,这是没有义务写的全缓冲,即使它几乎总是这样。问题中的无循环代码是一个错误。
亚当

Answers:


50

您可以在man 2 write以下位置找到答案:

如果此数目小于请求的字节数,这不是错误;例如,由于磁盘设备已装满,可能会发生这种情况。


并从write()手册页描述:

ssize_t write(int fd, const void *buf, size_t count);

根据POSIX.1,如果count大于SSIZE_MAX,则结果是实现定义的;有关Linux上的上限,请参见注释。

笔记

在Linux上write()(和类似的系统调用)将最多传输 0x7ffff000(2,147,479,552)字节,并返回实际传输的字节数。(在32位和64位系统上都是如此。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.