使用多个线程并发写入文件

时间:2011-08-24 21:53:42

标签: c linux concurrency pthreads block-device

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

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

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

1 个答案:

答案 0 :(得分:3)

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标志,您尝试写入的全部数据不需要在系统调用返回之前刷新到磁盘,而是需要足够的信息才能< em>从磁盘中检索 ...取决于你正在编写的内容,这可能比你打算写入磁盘的整个数据缓冲区要小得多,因此实际写的是所有的系统调用完成后,数据将在稍后的时间发生,并且该过程已转移到其他位置。

相关问题