【问题标题】:Concurrent writes to a file using multiple threads使用多个线程并发写入文件
【发布时间】:2011-08-24 21:53:42
【问题描述】:

我有一个用户级程序,它使用标志O_WRONLY|O_SYNC 打开一个文件。该程序创建了 256 个线程,每个线程尝试将 256 个或更多字节的数据写入文件。我希望总共有 1280000 个请求,总共有大约 300 MB 的数据。一旦完成 1280000 个请求,程序就会结束。

我使用pthread_spin_trylock() 来增加一个变量,该变量跟踪已完成的请求数。为了确保每个线程写入一个唯一的偏移量,我使用pwrite() 并根据已经写入的请求数计算偏移量。因此,我在实际写入文件时不使用任何互斥锁(这种方法是否确保数据完整性?)

当我检查 pwrite() 呼叫被阻止的平均时间以及使用 @ 找到的相应数字(即平均 Q2C 时间——这是 BIO 整个生命周期的时间度量)时987654321@,我发现有很大的不同。事实上,给定 BIO 的平均完成时间远大于 pwrite() 调用的平均延迟时间。这种差异背后的原因是什么?这些数字不应该相似吗,因为O_SYNC 确保数据在返回之前实际写入物理介质?

【问题讨论】:

    标签: c linux concurrency pthreads block-device


    【解决方案1】:

    pwrite() 应该是原子的,所以你应该在那里安全......

    关于您的系统调用和实际 BIO 之间的延迟差异,根据man-pages at kernel.org for open(2) 上的此信息:

    POSIX 提供了三种不同的同步 I/O 变体, 相应的 到标志 O_SYNC、O_DSYNC 和 O_RSYNC。目前(2.6.31), 仅限 Linux 实现 O_SYNC,但 glibc 将 O_DSYNC 和 O_RSYNC 映射到 相同的数字 值为 O_SYNC。大多数 Linux 文件系统实际上并不 实施 POSIX O_SYNC 语义,需要写入的所有元数据更新 在磁盘上 返回用户空间,但只有 O_DSYNC 语义, 只需要 检索它所需的实际文件数据和元数据 磁盘由 系统调用返回的时间。

    所以这基本上意味着使用O_SYNC 标志,您尝试写入的全部数据不需要在系统调用返回之前刷新到磁盘,而只需足够的信息即可从磁盘中检索它...取决于您正在写入的内容,这可能比您打算写入磁盘的整个数据缓冲区少很多,因此所有数据的实际写入将发生在稍后的时间,在系统调用完成并且进程转移到其他事情之后。

    【讨论】:

    • 我对 ext2 文件系统重复了同样的实验,与 ext3 文件系统不同,它不是日志文件系统。平均 Q2C 延迟结果为 8.5 毫秒。在用户级程序中,pwrite() 调用被阻塞的平均时间是 1.5 毫秒。与我之前的实验相比,这些数字相对接近;然而,这不是我想要的。如何使pwrite() 完全 同步调用,即只有在整个数据缓冲区写入磁盘后调用才返回?磁盘基准测试工具必须有解决方法?
    • 您可能不得不使用较低的内核级编写原语...根据 Linux 实现,pwrite() 不是完全同步的。
    猜你喜欢
    • 1970-01-01
    • 2015-08-17
    • 2015-11-26
    • 1970-01-01
    • 2015-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多