我有一个由C编写的程序。它计算一些东西并将输出写入文件。我的问题是它写的不超过2GB。我来一个简化的代码。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <malloc.h>
#include <errno.h>
int main() {
size_t size = 3221225472LL;
char *map = malloc(size);
size_t allocated = malloc_usable_size(map);
int fd = open("myfile", O_RDWR|O_CREAT|O_TRUNC, (mode_t)0644);
ssize_t written = write(fd, map, size);
return 0;
}
虽然正在创建输出文件“myfile”,但对于我请求的大小超过2GB的大小,大小总是2GB(2147479552字节)。malloc()成功分配了所请求大小的内存(在这种情况下,“已分配” “是3GB)。 write()之后的errno为0。
环境如下
汇编:
gcc code.c -D_FILE_OFFSET_BITS=64 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
这可能是什么原因?
增加: 得到两个回复后,我添加了重试代码如下:
int main() {
size_t size = 3221225472LL;
char *map = malloc(size);
size_t allocated = malloc_usable_size(map);
int fd = open("myfile", O_RDWR|O_CREAT|O_TRUNC, (mode_t)0644);
ssize_t written = write(fd, map, size);
while (written < size) {
written += write(fd, &map[written], size-written);
}
return 0;
}
答案 0 :(得分:13)
根据man page(强调我的)
在Linux上,
write()
(以及类似的系统调用)将传输 最多0x7ffff000(2,147,479,552)个字节 ,返回实际传输的字节数。 (在32位和64位系统上都是如此。)
答案 1 :(得分:4)
某些文件系统对文件大小有很大的限制,特别是FAT32。 disk quotas和资源限制(请参阅setrlimit(2)和RLIMIT_FSIZE
)都会限制文件大小(当然还有文件系统本身的可用空间)。
written
很可能(在你致电write(2)之后......)只有2 31 。你应该检查一下。
和write(2)文件:
在Linux上,write()(和类似的系统调用)最多会传输 0x7ffff000(2,147,479,552)个字节,返回字节数 实际转移。 (32位和64位都是如此 系统。)
当然,对write(2)的给定调用永远不应该写入所有必需的字节(这在所有POSIX系统上都是如此,并且在20世纪80年代的Unix系统上也是如此)。例如,write
到某些pipe(7)肯定无法写入那么多字节。
您可能更愿意使用<stdio.h>
缓冲 fwrite(3),但您应该检查返回的计数。
最后,您可以考虑在案例中使用mmap(2)。另请参阅msync(2)
请注意,对于大型文件,真正的瓶颈是硬件(磁盘本身)。因此,使用缓冲的fwrite
来提高性能并不重要。
(你在评论中提到了一个太字节文件)
BTW,对于大TB级数据集,使用一些更高级别的方法(特别是数据库,可能带有sqlite,或者索引文件àlaGDBM)实际上可能更有效,因为你是然后只能编写数据的部分(或因为RDBMS在远程数据库服务器上运行,例如使用MariaDB或PostGreSQL)。因人而异。但硬件带宽小于千兆字节/秒,因此写入1兆字节可能需要几个小时。即使使用巨大的交换大小,在32 GB的计算机上,如果没有thrashing,您将无法malloc
太字节。
您也可以巧妙地使用posix_fadvise(2)来略微提高性能(但并不多:对于TB级文件而言,瓶颈是硬件)