我想知道 Linux 读/写系统调用是否支持从多个线程或进程对单个磁盘文件的非重叠区域进行不同步读/写(非追加写入(。 每个线程将查找其自己的文件区域,并以独占方式访问此区域,永远不会与其他线程正在操作的区域重叠。
我想知道 linux 读/写系统调用是否支持 非同步读取/写入(非追加写入(到非重叠 来自多个线程或进程的单个磁盘文件的区域。每 线程将寻找它自己的文件区域,并从/到 该区域仅与该区域重叠,从不与其他区域重叠 线程正在运行。
POSIX 在 XSH 2.9.7 中指定,就其 POSIX 指定的效果而言,基本上所有 I/O 函数都是原子的。 给出了一长串适用的特定函数,open()
、lseek()
、read()
、write()
和close()
都在上面。 因此
如果两个线程分别调用其中一个函数,则每次调用应 要么查看另一个调用的所有指定效果,要么看不到 他们。
这不依赖于任何外部同步,即使对于与同一打开文件描述关联的文件描述符的操作也是如此。
同一个文件可以有多个打开的文件描述,即使是在单个进程中(例如,参见 open(2( 的手册页(。 给定多个线程通过引用不同打开文件描述的文件描述符对同一常规文件的非重叠区域执行read()
和write()
操作,POSIX 不提供期望这些操作相互干扰的基础,无论所涉及的线程的外部同步如何。 在实践中,它工作正常。
您可能会遇到麻烦的地方是所涉及的线程是否尝试使用引用相同打开文件描述的文件描述符。 这些不必是相同的文件描述符值(因此dup()
文件描述符在这里没有帮助(,线程也不必属于同一进程才能出现这种情况。 每个打开的文件描述都有一个关联的文件位置,因此,如果两个不同的线程尝试执行任务,每个线程都需要分别设置文件偏移量并将数据传输到文件或从文件传输数据,并且如果它们使用相同的打开文件描述,则各个函数调用的原子性不足以确保读取和写入在预期位置执行。 在这种情况下需要同步。
或者,正如@maximegorushkin注释中观察到的那样,@bk2204在另一个答案中观察到,pread()
和pwrite()
函数在一次调用中执行定位和数据传输。 这些也在原子 I/O 函数列表中,它们克服了基于每个数据传输的定位与数据传输的分离。 使用它们需要格外小心和簿记,并且在某些情况下它不能充分发挥作用,但它对于所讨论的特定情况可能是可行的。
因此,如果两个不同的线程想要在不同步的情况下对同一个文件进行操作,那么最安全、最通用的方法是让每个线程独立打开文件。 然后,只要它们的 I/O 操作仅限于文件的不相交区域,它们就不会相互干扰。 即使在文件的重叠区域进行操作也不是不可能,但这会带来更复杂的、特定于应用程序的注意事项。
是的,这是可能的。pread
和pwrite
函数允许您在给定偏移量处读取和写入文件,而无需更改文件偏移量。 它们专门设计用于允许在多线程程序中读取和写入。
您应该注意,在违反 POSIX 的情况下,pwrite
打开的文件描述符O_APPEND
将始终写入文件末尾。