我有一个userlevel程序,它使用标志O_WRONLY|O_SYNC
打开一个文件。该程序创建256个线程,尝试将256个或更多字节的数据写入文件。我希望总共有1280000个请求,总共大约300 MB的数据。一旦1280000个请求完成,程序就会结束。
我使用pthread_spin_trylock()
递增一个变量,该变量跟踪已完成的请求数。为了确保每个线程写入唯一的偏移量,我使用pwrite()
并计算偏移量作为已经写入的请求数量的函数。因此,在实际写入文件时我不使用任何互斥锁(这种方法是否确保数据完整性?)
当我检查pwrite()
呼叫被阻止的平均时间和相应的数字(即,平均Q2C时间 - 这是BIO完整生命周期的时间的度量)时使用blktrace
,我发现存在显着差异。实际上,给定BIO的平均完成时间远远大于pwrite()
呼叫的平均延迟时间。这种差异背后的原因是什么?这些数字不应该相似,因为O_SYNC
确保数据在返回之前实际写入物理介质吗?
答案 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>从磁盘中检索 ...取决于你正在编写的内容,这可能比你打算写入磁盘的整个数据缓冲区要小得多,因此实际写的是所有的系统调用完成后,数据将在稍后的时间发生,并且该过程已转移到其他位置。