Linux `在POSIX中编写`序列化

Linux `在POSIX中编写`序列化,linux,concurrency,posix,Linux,Concurrency,Posix,我试图在以下方面理解这一要求: 写入可以相对于其他读取和写入进行序列化。如果可以(通过任何方式)证明文件数据的read()发生在数据的write()之后,则它必须反映write(),即使调用是由不同的进程进行的。类似的要求也适用于对同一文件位置的多个写入操作 1) “发生”是指被调用的read,read成功返回,还是其他什么 2) 如果在一个进程调用读取时,另一个进程对同一个文件调用写入两次,是否存在读取将反映部分或全部第二次写入,而不是全部第一次写入的情况 |---------------

我试图在以下方面理解这一要求:

写入可以相对于其他读取和写入进行序列化。如果可以(通过任何方式)证明文件数据的read()发生在数据的write()之后,则它必须反映write(),即使调用是由不同的进程进行的。类似的要求也适用于对同一文件位置的多个写入操作

1) “发生”是指被调用的
read
read
成功返回,还是其他什么

2) 如果在一个进程调用
读取
时,另一个进程对同一个文件调用
写入
两次,是否存在读取将反映部分或全部第二次写入,而不是全部第一次写入的情况

  |----------------read-----------------|
      |--write1--|       |--write2--|

3) 实现(例如ext4)如何处理这一问题?这值得担心吗?

回答第一个问题:

“发生”是指从调用点到返回值点的整个读取过程。所有这些都必须发生在上一次写入之后和下一次写入之前。同一页是这样写的:

成功返回对常规文件的write()后:

  • 通过该写入操作修改的文件中每个字节位置的任何成功读取()都将返回write()为该位置指定的数据,直到再次修改这些字节位置为止

  • 任何后续对文件中相同字节位置的成功写入()都将覆盖该文件数据

POSIX对任何类型的交织都不做任何保证,因为实现额外的保证是相当困难的

关于第二个问题

同样,请参考上述报价。如果名为
write()
write()
的进程成功返回,则任何进程随后读取的任何数据都将反映写入的数据

因此答案是“是的,如果第一次写入()失败”

实施

ext4和几乎所有其他文件系统都使用页面缓存。页面缓存是文件数据(或其相关部分)的内存表示。需要进行的任何同步都是使用此表示完成的。在这方面,从文件中读写就像从共享内存中读写一样

顾名思义,页面缓存是用页面构建的。在大多数实现中,一个页面是一个4k内存的区域,读取和写入是在页面的基础上进行的

这意味着,例如ext4将在文件的同一4k区域上序列化读写操作,但12k写操作可能不是原子的

在AFAICT中,ext4不允许在同一页上并发多个写操作,或在同一页上并发读写操作,但这是无法保证的


编辑:文件系统(磁盘上)的块大小可能小于一个页面,在这种情况下,一些I/O可能以块大小的粒度进行,但这在原子性方面更不可靠。

要回答您的第一个问题

“发生”是指从调用点到返回值点的整个读取过程。所有这些都必须发生在上一次写入之后和下一次写入之前。同一页是这样写的:

成功返回对常规文件的write()后:

  • 通过该写入操作修改的文件中每个字节位置的任何成功读取()都将返回write()为该位置指定的数据,直到再次修改这些字节位置为止

  • 任何后续对文件中相同字节位置的成功写入()都将覆盖该文件数据

POSIX对任何类型的交织都不做任何保证,因为实现额外的保证是相当困难的

关于第二个问题

同样,请参考上述报价。如果名为
write()
write()
的进程成功返回,则任何进程随后读取的任何数据都将反映写入的数据

因此答案是“是的,如果第一次写入()失败”

实施

ext4和几乎所有其他文件系统都使用页面缓存。页面缓存是文件数据(或其相关部分)的内存表示。需要进行的任何同步都是使用此表示完成的。在这方面,从文件中读写就像从共享内存中读写一样

顾名思义,页面缓存是用页面构建的。在大多数实现中,一个页面是一个4k内存的区域,读取和写入是在页面的基础上进行的

这意味着,例如ext4将在文件的同一4k区域上序列化读写操作,但12k写操作可能不是原子的

在AFAICT中,ext4不允许在同一页上并发多个写操作,或在同一页上并发读写操作,但这是无法保证的


编辑:文件系统(磁盘上)的块大小可能小于一个页面,在这种情况下,一些I/O可能以块大小的粒度进行,但就原子性而言,这就更不可靠了。

我非常确定读和写是原子的。也就是说,结果就像是按照开始的顺序完成的一样。因此,在您的示例中,该读取将首先“完成”,然后write1将在write2之前完成(假设在您的图中时间从左向右流逝)。当然,HDD/SDD上实际发生的情况可能与执行这些读写操作的应用程序发生的情况不同-文件系统驱动程序可能会做一些聪明的事情,优化写操作等…感谢您的回复!然而,对标准的这种解释似乎与报告中的观察结果相冲突。也许我错过了什么