我知道内核保证,如果没有插入,一定大小(它被认为是PIPE_BUF,4096Bytes)的数据是原子写入的,这意味着其他进程正试图读取块。
然而我一直想知道,如果我将更多的数据块(比如说“abc ... [x bytes] ... xyz”)写入存储设备,那么在内核执行操作期间,内核首先写abc,xyz最后?
如果没有,那么在写入操作完成之前,可能会发生一些其他进程读取“ * ... [x bytes] ... xyz”。我认为这对许多应用来说无疑是一场灾难。
有人知道实现,或者,我在哪里可以找到内核源代码中的答案?
期待您的回复!谢谢!
[更新2011.11.12]
我查看了源代码,但我无法完全理解它。我发现了调用链“write - > vfs_write - > do_sync_write [loops] - > generic_file_aio_write [inode_mutex] - > __generic_file_aio_write - > .. - > generic_perform_write - > .. - > __copy_from_user(to ,来自,n)
__ copy_from_user是一个使用体系结构相关的asm代码实现的宏/函数,我现在无法理解它们。但我认为编码人员会这样做,因为我们大多数人都认为它应该是什么......
希望能够进一步澄清〜
答案 0 :(得分:3)
数据可能没有按照您编写的顺序物理刷新到磁盘,因此如果机器在写入过程中崩溃,您可能在系统之后看到“xyz”而没有“abc”靴子备份。但假设机器保持运行,内核将确保所有写入都以正确的顺序发生。
答案 1 :(得分:2)
始终遵守正确的顺序。
但是在对具有多个编写器的接收器进行非原子写入时,可能会发生接收到的数据包含"abc...[n bytes]...[data from other writer]...[m bytes]...xyz"
,其中n+m=x
。
因此数据插入一个完全不同的数据块。
在原子写作中,这样的事情不会发生。
编辑:要明确,这只是关于管道和FIFO。文件怎么样,我不知道。
答案 2 :(得分:0)
让我说我写的是abc,即4k,而def,也就是4k。
内核不保证如果我在8k块中写“abcdef”,那另一个进程将看不到“abc”,然后将“def”看作两个单独的写入。
但如果我只写4k的“abc”,内核保证任何其他进程永远不会看到“a”然后“b”然后“c”
http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_14.html#SEC215
你在另一条轨道上。您想要的保证是“aby”之前永远不会读取“xyz”。这完全是一个不同的保证。事实上,这不仅仅是一种保证。不言而喻。它与将磁盘刷新到磁盘无关。这是系统的不同层次。