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

34

我基本上有以下代码:

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字节没有写入。我可以通过将write操作放入循环并移动缓冲区来解决这个问题,但我很好奇为什么它总是失败。

例如,如果文件大小为2147483648,则write只写入2147479552,留下4096未写入。为什么会发生这种情况,是否总是需要在循环中进行write操作?


2
你是在32位模式下运行吗?2G是32位数字的最大值。 - Barmar
2
“write” 函数一次性写入多少数据取决于要写入的数据类型和目标文件对象(例如:普通文件,管道,流套接字,数据报套接字等)。您能具体说明一下吗? - zwol
7
等一下,你是不是试图一次性“写入”整个文件?通常的方法是按缓冲区大小逐块传输数据,直到全部写入。 - Luaan
4
如果你已经拥有了所有的数据,我认为一次性将它们全部写入是没有任何问题的。但正如这个问题和回答所展示的那样,“write()”并不一定要一次性写入所有数据(即使是小缓冲区也一样)。 - pipe
8
我可以通过在循环中包装write来解决这个问题,而不考虑SSIZE_MAX的限制。write()函数规范说明它没有义务写入整个缓冲区,即使它几乎总是这样做。问题中没有循环的代码是有问题的。 - Adam
显示剩余7条评论
1个回答

53
你可以在man 2 write中找到答案:

如果这个数字比请求的字节数小,这并不是一个错误;这可能会发生,例如因为磁盘设备已经满了。


并且从write()手册页描述中得知:

ssize_t write(int fd, const void *buf, size_t count);
根据POSIX.1标准,如果 count 大于 SSIZE_MAX,则结果是实现定义的;有关Linux上限的信息,请参见NOTES。
NOTES:
在Linux上,write()(以及类似的系统调用)最多传输 0x7ffff000(2,147,479,552)个字节,并返回实际传输的字节数。(这对32位和64位系统都成立。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接