【问题标题】:Can multiple threads/processes read/write from/to non-overlapping regions of a file simultaneously without synchronization?多个线程/进程可以在不同步的情况下同时读取/写入文件的非重叠区域吗?
【发布时间】:2019-08-31 16:36:04
【问题描述】:

我想知道 Linux 读/写系统调用是否支持从多个线程或进程对单个磁盘文件的非重叠区域进行非同步读/写(非附加写入)。每个线程将寻找文件中自己的区域,并以独占方式访问该区域,而不会与其他线程正在操作的区域重叠。

【问题讨论】:

    标签: c++ linux multithreading file concurrency


    【解决方案1】:

    我想知道linux读/写系统调用是否支持 非同步读/写(非附加写)到非重叠 来自多个线程或进程的单个磁盘文件的区域。每个 线程将寻找它自己的文件区域,并从/到读/写 该区域专有,从不与其他区域重叠 线程正在运行。

    POSIX 在XSH 2.9.7 中指定基本上所有的 I/O 函数就其 POSIX 指定的效果而言彼此之间都是原子的。给出了一长串适用的特定函数,open()lseek()read()write()close() 都在上面。因此,

    如果两个线程分别调用其中一个函数,则每次调用都应 要么看到另一个调用的所有指定效果,要么没有 他们。

    这不依赖于任何外部同步,即使是对与相同打开文件描述相关联的文件描述符的操作。

    同一个文件可以有多个打开的文件描述,即使在一个进程中也是如此(例如,参见open(2) 的手册页)。鉴于多个线程在同一常规文件的非重叠区域上执行 read()write() 操作,通过引用不同打开文件描述的文件描述符,POSIX 没有提供任何依据来期望这些操作会干扰相互之间,无论涉及的线程的外部同步如何。在实践中,它工作得很好。

    你会遇到麻烦的地方是如果涉及的线程试图使用引用相同打开文件描述的文件描述符。这些不必是相同的文件描述符值(因此dup()ing 文件描述符在这里没有帮助),线程也不必属于同一进程才能出现这种情况。每个打开的文件描述都有一个关联的文件位置,因此如果两个不同的线程正在尝试执行每个都需要单独设置文件偏移量并将数据传输到文件或从文件传输数据的任务,并且如果它们正在使用相同的打开文件描述,则单个函数调用的原子性不足以确保在预期位置执行读取和写入。在这种情况下需要同步。

    或者,正如在 cmets 中观察到的 @maximegorushkin 和在另一个答案中观察到的 @bk2204 那样,pread()pwrite() 函数在单个调用中执行定位和数据传输。这些也在原子 I/O 函数列表中,它们克服了基于每个数据传输的定位与数据传输的分离。使用它们需要额外的注意和记账,并且在某些情况下它不能充分发挥作用,但它对于所讨论的特定情况可能仍然可行。

    因此,如果两个不同的线程想要在不同步的情况下对同一个文件进行操作,那么最安全和最通用的方法是让每个线程独立打开文件。只要它们的 I/O 操作仅限于文件的不相交区域,它们就不会相互干扰。即使在文件的重叠区域上进行操作也不是不可能的,但这会引入更复杂的、特定于应用程序的注意事项。

    【讨论】:

    • 谢谢,这看起来不错,我没有想到需要多次打开的警告,但这很有意义,并且可能节省了一个困难的调试场景!
    【解决方案2】:

    是的,这是可能的。 preadpwrite 函数允许您在给定偏移量处读取和写入文件,而无需更改文件偏移量。它们专门设计用于允许在多线程程序中进行读写。

    您应该注意,违反 POSIX,使用O_APPEND 打开的文件描述符上的pwrite 将始终写入文件末尾。

    【讨论】:

    • 谢谢,我不知道这些 linux 系统调用,它们看起来像我需要的,并且可以避免多次打开,正如@john bollinger 指出的那样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-05
    • 1970-01-01
    • 1970-01-01
    • 2012-01-26
    • 1970-01-01
    • 2015-03-02
    • 1970-01-01
    相关资源
    最近更新 更多