flush()不一定将文件的数据写入磁盘.使用flush()后跟os.fsync()来确保此行为.
所以我的问题是:Python到底在flush
做什么?我认为它强制将数据写入磁盘,但现在我发现它没有.为什么?
我认为fsync()在内部执行fflush(),因此在流上使用fsync()是可以的.但是我在网络I/O下执行时会得到意想不到的结果.
我的代码片段:
FILE* fp = fopen(file, "wb");
/* multiple fputs() calls like: */
fputs(buf, fp);
...
...
fputs(buf.c_str(), fp);
/* get fd of the FILE pointer */
fd = fileno(fp);
#ifndef WIN32
ret = fsync(fd);
#else
ret = _commit(fd);
fclose(fp);
Run Code Online (Sandbox Code Playgroud)
但似乎_commit()并没有刷新数据(我在Windows上试过并且数据是在Linux导出的文件系统上编写的).
当我将代码更改为:
FILE* fp = fopen(file, "wb");
/* multiple fputs() calls like: */
fputs(buf, fp);
...
...
fputs(buf.c_str(), fp);
/* fflush the data */
fflush(fp);
fclose(fp);
Run Code Online (Sandbox Code Playgroud)
这次它会刷新数据.
我想知道_commit()是否与fflush()做同样的事情.有什么投入?
rename(tmppath, path)
没有先拨打电话是否安全fsync(tmppath_fd)
?
我希望路径始终指向一个完整的文件.我主要关心的是Ext4.在所有未来的Linux内核版本中,rename()承诺是否安全?
Python中的一个用法示例:
def store_atomically(path, data):
tmppath = path + ".tmp"
output = open(tmppath, "wb")
output.write(data)
output.flush()
os.fsync(output.fileno()) # The needed fsync().
output.close()
os.rename(tmppath, path)
Run Code Online (Sandbox Code Playgroud) 我想确保已将一个ofstream写入磁盘设备.这样做的便携方式(可在POSIX系统上移植)是什么?
如果我open
将文件分别以只读附加模式获取文件描述符并fsync
用它调用,那么这是否解决了问题?像这样:
ofstream out(filename);
/* ...
write content into out
...
*/
out.close();
int fd = open(filename, O_APPEND);
fsync(fd);
close(fd);
Run Code Online (Sandbox Code Playgroud) 在POSIX文件系统中持久重命名文件的正确方法是什么?特别想知道目录上的fsyncs .(如果这取决于OS/FS,我问的是Linux和ext3/ext4).
注意:在StackOverflow上还有关于持久重命名的其他问题,但是AFAICT它们没有解决fsync-ing目录(这对我来说很重要 - 我甚至不修改文件数据).
我目前有(在Python中):
dstdirfd = open(dstdirpath, O_DIRECTORY|O_RDONLY)
rename(srcdirpath + '/' + filename, dstdirpath + '/' + filename)
fsync(dstdirfd)
Run Code Online (Sandbox Code Playgroud)
具体问题:
提前致谢.
Tim Bray的文章"安全地保存数据"给我留下了悬而未决的问题.今天,已经有一个多月了,我还没有看到任何跟进,所以我决定在这里讨论这个话题.
本文的一点是,在使用FileOutputStream时,应该调用FileDescriptor.sync()以保证安全.起初,我非常恼火,因为在我做Java的12年中,我从未见过任何Java代码进行同步.特别是因为处理文件是一件非常基本的事情.此外,FileOutputStream的标准JavaDoc从未暗示过同步(Java 1.0 - 6).经过一番研究,我认为ext4实际上可能是第一个需要同步的主流文件系统.(是否有建议使用显式同步的其他文件系统?)
我很欣赏这方面的一些一般性想法,但我也有一些具体的问题:
FileOutputStream fileOut = ctx.openFileOutput(file, Context.MODE_PRIVATE);
BufferedOutputStream out = new BufferedOutputStream(fileOut);
try {
out.write(something);
out.flush();
fileOut.getFD().sync();
} finally {
out.close();
}
我boost::filesystem::create_directories()
用来创建新目录.当我在创建后不久尝试访问这些目录时,我收到一条错误消息:没有这样的目录.但如果我在创建目录后睡了一会儿一切都很好(我没有得到错误).此外,我尝试使用fsync()
和sync()
创建目录后,但它没有任何区别.我在ext4和xfs文件系统上测试它,我的boost版本是boost 1.44
我的问题是
boost::create_directories()
立即创建目录?或者有可能出现问题吗?sync()
并fsync()
保证在ext4/xfs上将所有内容刷新到光盘上吗?我知道已经有类似的问题,我给了他们一个看,但我找不到一个明确的单一答案我的问题.我只是在网上调查这些函数及其与内存层的关系.特别是我发现这篇精美的文章让我对内存层有了很好的了解
似乎fflush()
将数据从应用程序移动到内核文件系统缓冲区并且没关系,每个人似乎都同意这一点.令我困惑的唯一一件事就是在同一篇文章中他们假设一个回写缓存,说fsync()
"数据被保存到稳定的存储层",并且在他们添加"存储本身可以将数据存储在写入中"之后-back cache,因此fsync()
仍然需要使用O_DIRECT打开的文件,以便将数据保存到稳定存储"
在这里和那里阅读似乎事实就是这样fsync()
,sync()
让数据进入存储设备,但如果这个数据有缓存层,它只是移动到这里,而不是立即存储到永久存储,如果出现电源故障,数据甚至可能会丢失.除非我们有一个启用了障碍的文件系统,然后" sync()
/ fsync()
和其他一些操作将导致相应的CACHE FLUSH(ATA)或SYNCHRONIZE CACHE(SCSI)命令被发送到设备"[来自您的网站答案 ]
问题:
如果要更新的数据已经在内核缓冲区中并且我的设备在回写模式下有一个易失性缓存层,那么就像文章所说的那样,像fsync()
[和sync()
我想的那样]操作将数据同步到稳定的内存层跳过易变的?我认为这是通过直写缓存而不是回写缓存所发生的情况.从我读到的内容中我了解到,使用回写式缓存fsync()
可以将数据发送到设备,将数据放入易失性缓存中,只有在之后才能进入永久性内存
我读过它fsync()
使用文件描述符,然后使用单个文件,同时sync()
导致缓冲区的完全部署,因此它适用于每个要更新的数据.并且从该页面还fsync()
等待写入磁盘sync()
的结束,而不等待实际写入磁盘的结束.两者之间的内存数据传输是否存在其他差异?
感谢那些愿意帮助的人
我担心我会iotop
在一个完全空闲的系统上看到磁盘LED和每隔几秒钟进行的一些写操作,主要来自铬的过程.
对磁盘进行如此大量的写入完全没有任何意义,对SSD磁盘来说更少.对我来说读取不是问题,也因为我的20gb RAM笔记本上有足够的磁盘缓存.
该commit
选项(默认情况下为30秒)显然是解决不了问题.试图增加甚至减少,仍然每隔几秒钟就会看一次.
那么有没有办法强制每个任意间隔不超过一次写入?