Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix 从文件中读取,同时重新写入完全相同的数据_Unix_Io_Parallel Processing - Fatal编程技术网

Unix 从文件中读取,同时重新写入完全相同的数据

Unix 从文件中读取,同时重新写入完全相同的数据,unix,io,parallel-processing,Unix,Io,Parallel Processing,假设我有两个线程:第一个线程使用pwrite将数据块写入文件,第二个线程使用pread从中读取字节。让我们做两个假设: 1) 读取线程可以读取文件的一个字节当且仅当写入线程已经向其写入了某些内容时 2) 写入线程从不将不同的数据写入文件的同一字节,但偶尔可以重写它以前写入的完全相同的数据 假设读取线程在写入线程重写数据的同时读取一些数据。读线程是否可能最终接收到损坏的数据?我不知道在您描述的条件下,对读/写原子性有任何实际要求 首先,从POSIX来看,有以下两个要求: 在常规文件或其他能够查找的

假设我有两个线程:第一个线程使用
pwrite
将数据块写入文件,第二个线程使用
pread
从中读取字节。让我们做两个假设:

1) 读取线程可以读取文件的一个字节当且仅当写入线程已经向其写入了某些内容时

2) 写入线程从不将不同的
数据写入文件的同一字节,但偶尔可以重写它以前写入的完全相同的数据


假设读取线程在写入线程重写数据的同时读取一些数据。读线程是否可能最终接收到损坏的数据?

我不知道在您描述的条件下,对读/写原子性有任何实际要求

首先,从POSIX来看,有以下两个要求:

在常规文件或其他能够查找的文件上,实际写入 数据的保存应从文件中的以下位置开始: 与fildes关联的文件偏移量。在成功从 write(),文件偏移量应增加字节数 实际上写的。在常规文件中,如果最后一个字节的位置 Write大于或等于文件的长度,即 文件的位置应设置为该位置加1

附加到文件是原子的:

如果设置了文件状态标志的O_APPEND标志,则文件偏移量 应在每次写入之前设置为文件末尾,且 文件修改操作应在更改之间进行 文件偏移量和写入操作

虽然这并不是对所有写调用的原子性的明确要求,但我无法想象现实世界中的文件系统如何以满足这些要求的方式实现,而不隐式地提供原子写调用。如果数据的传输和文件偏移量的更新必须是一个组合的原子操作,那么这就意味着传输本身必须是原子操作

现在,添加此明确要求:

对管道或FIFO的写入请求应以与管道相同的方式处理 常规文件,但以下例外情况除外:

  • 小于等于{PIPE_BUF}字节的写入请求不得与在同一管道上进行写入的其他进程的数据交错。大于{PIPE_BUF}字节的写操作可能在任意边界上与其他进程的写操作交错,无论是否设置了文件状态标志的O_NONBLOCK标志
这似乎适合您的需要,但这仅适用于其他写入操作。同步读取操作根本没有提到。请注意,即使是
PIPE_BUF
原子写入要求也受到“不应与其他进程的数据交错”的限制

据我所知,任何读取操作都必须以原子方式“查看”写入的数据。POSIX国家

标准开发人员考虑将原子性要求添加到 管道或FIFO,但由于管道和FIFO的性质 无法保证{PIPE_BUF}或任何 其他有助于应用程序可移植性的大小

I/O对于普通文件、管道和FIFO来说是原子的。 原子表示从单个操作开始的所有字节 输出一起结束,而不与其他I/O交叉 操作。终端的一个已知属性是,这不是 并且终端是显式的(隐式的永久性的) 例外,使行为不明确。他人的行为 设备类型也未指定,但措辞旨在 暗示未来的标准可能会选择指定原子性(或 不)

因此,对读取操作的原子性没有明确的要求

但现实世界中的实现再次发挥作用。磁盘是块设备。磁盘上的文件按块分配。页面缓存以页面大小的块为单位。我看不到任何方法可以对任何特定的数据块执行写入操作,这些数据块在更新该块中的数据时不需要锁定该块。所以,只要您停留在页面缓存的单个块内(假设正常的缓存IO操作),我敢说原子性几乎肯定是有保证的

但是,您将依赖于实现细节——即使这样,也只有在页面缓存中的单个页面中才能使用。跨页面边界甚至实现细节可能无法提供跨写/读周期的原子性尝试

由于这些实现细节,您可能会观察到原子行为——假设小到中等大小的更新,因此不太可能跨越页面边界。即使如此,跨越页面边界也将按顺序进行,当更新从A页跨越到B页时,锁定A页的第一个线程也可能是锁定B页的第一个线程。不能保证锁定A页和B页以进行挂起的写入操作会阻止对B页的读取访问,而只有A页正在被更新,这同样依赖于实现细节可能有用

所以我不能保证我能看到

这样看:内存中简单值(如
unsigned long
)的读写不能保证是原子的


这甚至不能解决这样一个事实,即读写操作并不能保证在第一时间传输所有请求的数据。

非常感谢您的回复。虽然它没有直接回答这个问题,但它展示了一些思考我遇到的特定bug的新方法。