我对大文件ftruncate
和fsync
操作感到惊讶。我编写了一个程序,在Linux 64位系统上创建一个空文件,将其截断为0xffffffff字节,然后将其截断为fsync
。
在所有操作之后,使用此长度正确创建文件。
我发现ftruncate
费用大约为1442微秒,fsync
费用仅为4微秒。
这种高性能是正常的吗?真的是在光盘上写下所有字节吗?如果没有,我该如何确保同步?
#include <sys/time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
static const size_t __tamFile__ = 0xffffffff;
int main(int, char **)
{
std::string fichero("./testTruncate.dat");
unlink(fichero.c_str());
int fd = open(fichero.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (fd != -1)
{
struct timeval t1, t2;
timerclear(&t1);
timerclear(&t2);
gettimeofday(&t1, NULL);
ftruncate(fd, __tamFile__);
gettimeofday(&t2, NULL);
unsigned long long msecTruncate = static_cast<unsigned long long>((((t2.tv_sec * 1E6) + t2.tv_usec) - ((t1.tv_sec * 1E6) + t1.tv_usec))) ;
gettimeofday(&t1, NULL);
fdatasync(fd);
gettimeofday(&t2, NULL);
unsigned long long msecFsync = static_cast<unsigned long long>((((t2.tv_sec * 1E6) + t2.tv_usec) - ((t1.tv_sec * 1E6) + t1.tv_usec))) ;
std::cout << "Total microsec truncate: " << msecTruncate << std::endl;
std::cout << "Total microsec fsync: " << msecFsync << std::endl;
close(fd);
}
return 0;
}
答案 0 :(得分:7)
我编写了一个在Linux 64位系统上创建空文件的程序, 将其截断为0xffffffff字节,然后将其截断为fsync。
除非你写一些内容,否则该文件极有可能包含漏洞。
来自TLPI:
如果程序寻找超过文件末尾会发生什么,然后呢 执行I / O?对read()的调用将返回0,表示文件结束。 有点令人惊讶的是,可以在任意位置写入字节 指向文件末尾。
前一个结束之间的空间 文件和新写入的字节被称为文件孔。 从编程的角度来看,孔中的字节存在,和 从空洞读取返回包含0的空字符缓冲区(null 个字节)。
但是,文件孔不会占用任何磁盘空间。文件 在某些情况下,系统不会为某个孔分配任何磁盘块 稍后,将数据写入其中。
答案 1 :(得分:0)
您拥有哪个Linux内核版本,哪个文件系统以及哪些挂载选项(特别是启用了屏障?)?
在Linux 2.6.32 64位,ext4启用了屏障(默认),我得到了
$ ~/src/cpptest/truncsync
Total microsec truncate: 32
Total microsec fsync: 266
Total microsec close: 14
否则相同,但是使用NFS挂载的文件系统,我得到了
$ ./truncsync
Total microsec truncate: 38297
Total microsec fsync: 6
Total microsec close: 6
$ ./truncsync
Total microsec truncate: 3454967
Total microsec fsync: 8
Total microsec close: 330