使用多个线程并发写入文件
作者:互联网
我有一个userlevel程序,它使用标志O_WRONLY | O_SYNC打开一个文件.该程序创建256个线程,尝试将256个或更多字节的数据写入文件.我希望总共有1280000个请求,总共大约300 MB的数据.一旦1280000个请求完成,程序就结束了.
我使用pthread_spin_trylock()来递增一个变量,该变量跟踪已完成的请求数.为了确保每个线程写入唯一的偏移量,我使用pwrite()并将偏移量计算为已经写入的请求数的函数.因此,在实际写入文件时我不使用任何互斥锁(这种方法是否确保数据完整性?)
当我检查pwrite()调用被阻止的平均时间和使用blktrace
找到的相应数字(即,平均Q2C时间 – 这是BIO完整生命周期时间的度量)时,我发现这是一个显着的差异.实际上,给定BIO的平均完成时间远远大于pwrite()调用的平均延迟时间.这种差异背后的原因是什么?这些数字不应该相似,因为O_SYNC确保数据在返回之前实际写入物理介质吗?
解决方法:
pwrite()假设是原子的,所以你应该安全…
关于系统调用与实际BIO之间的延迟差异,根据man-pages at kernel.org for open(2)的信息:
POSIX provides for three different variants of synchronized I/O,
corresponding
to the flags O_SYNC, O_DSYNC, and O_RSYNC. Currently (2.6.31),
Linux only
implements O_SYNC, but glibc maps O_DSYNC and O_RSYNC to the
same numerical
value as O_SYNC. Most Linux file systems don’t actually
implement the POSIX
O_SYNC semantics, which require all metadata updates of a write
to be on disk
on returning to userspace, but only the O_DSYNC semantics,
which require only
actual file data and metadata necessary to retrieve it to be on
disk by the
time the system call returns.
所以这基本上意味着使用O_SYNC标志,您尝试写入的全部数据不需要在系统调用返回之前刷新到磁盘,而是需要足够的信息才能从磁盘中检索它…在你写的东西上,这可能比你打算写入磁盘的整个数据缓冲区要小得多,因此所有数据的实际写入将在稍后的系统调用之后进行.完成后,该过程已转移到其他方面.
标签:c-3,linux,concurrency,pthreads,block-device 来源: https://codeday.me/bug/20190630/1337547.html