我试图为文件操作预分配磁盘空间,但是,我遇到一个奇怪的问题,posix_fallocate只分配一个字节,当我调用它来分配磁盘空间的文件打开以追加模式和文件内容也意外。 有没有人知道这个问题? 而我的testing代码是,
#include <cstdio> #include <fcntl.h> #include <unistd.h> #include <sys/stat.h> #include <cerrno> int main(int argc, char **argv) { FILE *fp = fopen("append.txt", "w"); for (int i = 0; i < 5; ++i) fprintf(fp, "## Test loop %d\n", i); fclose(fp); sleep(1); int fid = open("append.txt", O_WRONLY | O_APPEND); struct stat status; fstat(fid, &status); printf("INFO: sizeof 'append.txt' is %ld Bytes.\n", status.st_size); int ret = posix_fallocate(fid, (off_t)status.st_size, 1024); if (ret) { switch (ret) { case EBADF: fprintf(stderr, "ERROR: %d is not a valid file descriptor, or is not opened for writing.\n", fid); break; case EFBIG: fprintf(stderr, "ERROR: exceed the maximum file size.\n"); break; case ENOSPC: fprintf(stderr, "ERROR: There is not enough space left on the device\n"); break; default: break; } } fstat(fid, &status); printf("INFO: sizeof 'append.txt' is %ld Bytes.\n", status.st_size); char *hello = "hello world\n"; write(fid, hello, 12); close(fid); return 0; }
而预期的结果应该是,
## Test loop 0 ## Test loop 1 ## Test loop 2 ## Test loop 3 ## Test loop 4 hello world
但是,上述scheme的结果是,
## Test loop 0 ## Test loop 1 ## Test loop 2 ## Test loop 3 ## Test loop 4 ^@hello world
那么,什么是“^ @”?
消息显示,
INFO: sizeof 'append.txt' is 75 Bytes. INFO: sizeof 'append.txt' is 76 Bytes.
任何线索?
谢谢
是的,posix_fallocate 可以在APPEND模式下打开文件。 如果你的文件系统支持fallocate
系统调用。 如果你的文件系统不支持它,glibc仿真会在APPEND模式下添加一个0字节到最后。
这是一个奇怪的,真让我感到困惑。 我通过使用strace
程序找到了答案,它显示了正在进行的系统调用。
看一下这个:
fallocate(3,0,74,1000)= -1 EOPNOTSUPP(不支持的操作)
fstat(3,{st_mode = S_IFREG | 0664,st_size = 75,…})= 0
fstatfs {f_type = 0xf15f,f_bsize = 4096,f_blocks = 56777565,f_bfree = 30435527,f_bavail = 27551380,f_files = 14426112,f_ffree = 13172614,f_fsid = {1863489073,-1456395543},f_namelen = 143,f_frsize = 4096} )= 0
pwrite(3,“\ 0”,1,1073)= 1
它看起来像GNU C图书馆试图帮助你在这里。 fallocate
系统调用显然没有在你的文件系统中实现,所以GLibC通过使用pwrite
在请求的分配结尾写入一个0字节来模拟它,从而扩展文件。
这在正常写入模式下工作正常。 但在APPEND模式下,写操作总是在文件末尾完成,所以pwrite
在pwrite
写入一个0字节。
不是什么意图。 可能是一个GNU C库的bug。
它看起来像ext4支持fallocate
。 如果我把这个文件写入/ tmp就行了。 它在我的主目录中失败,因为我正在Ubuntu中使用ecryptfs文件系统加密的主目录
每POSIX :
如果offset + len超出当前文件大小,那么posix_fallocate()将调整文件大小以偏移+ len。 否则,文件大小不应该改变。
因此,使用posix_fallocate
和append模式是没有意义的,因为它将扩展文件的大小(填充空字节),随后的写入将发生在空字节之后的空字符中。
至于为什么只扩展一个字节的文件,你确定这是正确的吗? 你有没有测量? 这听起来像是一个执行中的错误。