unix原子中的写操作吗? [英] Is a write operation in unix atomic?

查看:57
本文介绍了unix原子中的写操作吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读 APUE (UNIX环境中的高级编程),并在看到$ 3.11时遇到此问题:

I was reading the APUE(Advanced Programming in the UNIX Environment), and come across this question when I see $3.11:

if (lseek(fd, 0L, 2) < 0) /* position to EOF */
err_sys("lseek error");
if (write(fd, buf, 100) != 100) /* and write */
err_sys("write error")

APUE说:

这对于单个进程很好,但是如果多个进程使用此技术将其附加到同一文件,则会出现问题........这里的问题是,我们的逻辑操作是'到文件末尾的位置和写"需要两个单独的函数调用(如我们所示).任何需要多个函数调用的操作都不能是原子操作,因为内核总是有可能在两个函数调用之间暂时挂起进程.

它只是说cpu会在 lseek write 之间的函数调用之间切换,我想知道它是否也会切换成一半的 write 手术?或更确切地说, write 是原子的吗?如果线程A写"aaaaa" ,线程B写"bbbbb" ,结果将是"aabbbbbaaa" 吗?

It just says cpu will switch between function calls between lseek and write, I want to know if it will also switch in half write operation? Or rather, is write atomic? If threadA writes "aaaaa", threadB writes "bbbbb", will the result be "aabbbbbaaa"?

此外,在APUE说 pread pwrite 都是原子操作之后,这是否意味着这些函数使用了 mutex 在内部锁定是原子的?

What's more,after that APUE says pread and pwrite are all atomic operations, does that mean these functions use mutex or lock internally to be atomic?

推荐答案

要将Posix语义称为原子",也许是一个过分的简化.Posix要求读写以某种顺序进行:

To call the Posix semantics "atomic" is perhaps an oversimplification. Posix requires that reads and writes occur in some order:

可以针对其他读取和写入对写入进行序列化.如果可以证明文件数据的 read()(以任何方式)发生在数据的 write()之后,则它必须反映该 write(),即使调用是由不同的进程进行的.类似的要求适用于对同一文件位置的多次写入操作.这是保证数据从 write()调用到后续 read()调用的传播所必需的.(摘自 Posix规范 pwrite 和 write )

Writes can be serialized with respect to other reads and writes. If a read() of file data can be proven (by any means) to occur after a write() of the data, it must reflect that write(), even if the calls are made by different processes. A similar requirement applies to multiple write operations to the same file position. This is needed to guarantee the propagation of data from write() calls to subsequent read() calls. (from the Rationale section of the Posix specification for pwrite and write)

APUE中提到的原子性保证是指使用 O_APPEND 标志,该标志强制在文件末尾执行写操作:

The atomicity guarantee mentioned in APUE refers to the use of the O_APPEND flag, which forces writes to be performed at the end of the file:

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

If the O_APPEND flag of the file status flags is set, the file offset shall be set to the end of the file prior to each write and no intervening file modification operation shall occur between changing the file offset and the write operation.

关于 pread pwrite ,APUE说(当然是正确的),这些接口允许应用程序自动搜索和执行I/O.换句话说,无论任何其他进程执行什么操作,I/O操作都将在指定的文件位置进行.(因为位置是在调用本身中指定的,并且不会影响持久文件的位置.)

With respect to pread and pwrite, APUE says (correctly, of course) that these interfaces allow the application to seek and perform I/O atomically; in other words, that the I/O operation will occur at the specified file position regardless of what any other process does. (Because the position is specified in the call itself, and does not affect the persistent file position.)

Posix排序保证如下(来自 write() pwrite()函数的说明):

The Posix sequencing guarantee is as follows (from the Description of the write() and pwrite() functions):

对常规文件执行write()成功返回后:

After a write() to a regular file has successfully returned:

  • 通过该写操作修改的文件中每个字节位置的任何成功的 read()都应返回该位置的write()指定的数据,直到这些字节位置再次出现为止修改.

  • Any successful read() from each byte position in the file that was modified by that write shall return the data specified by the write() for that position until such byte positions are again modified.

任何随后成功执行 write()到文件中相同字节位置的操作,都将覆盖该文件数据.

Any subsequent successful write() to the same byte position in the file shall overwrite that file data.

如基本原理中所述,此措辞确实保证了两个同时进行的 write 调用(即使在不同的不相关进程中)也不会交织数据,因为如果在写操作期间对数据进行了交织,则写操作最终将成功完成.第二保证将无法提供.如何完成此操作取决于实施.

As mentioned in the Rationale, this wording does guarantee that two simultaneous write calls (even in different unrelated processes) will not interleave data, because if data were interleaved during a write which will eventually succeed the second guarantee would be impossible to provide. How this is accomplished is up to the implementation.

必须注意,并非所有文件系统都符合Posix,并且模块化OS设计(允许多个文件系统在一个安装中共存)使内核本身无法提供有关 write 的保证.适用于所有可用的文件系统.网络文件系统特别容易发生数据争用(并且本地互斥锁也无济于事),正如Posix所提到的(在基本原理"引用的段落的最后):

It must be noted that not all filesystems conform to Posix, and modular OS design, which allows multiple filesystems to coexist in a single installation, make it impossible for the kernel itself to provide guarantees about write which apply to all available filesystems. Network filesystems are particularly prone to data races (and local mutexes won't help much either), as is mentioned as well by Posix (at the end of the paragraph quoted from the Rationale):

对于某些缓存方案违反了这些语义的网络文件系统,此要求特别重要.

This requirement is particularly significant for networked file systems, where some caching schemes violate these semantics.

第一保证(关于后续读取)需要在文件系统中进行一些簿记,因为已经成功地写入"了数据.到内核​​缓冲区但尚未同步到磁盘的文件必须透明地可供从该文件读取的进程使用.这还需要对内核元数据进行一些内部锁定.

The first guarantee (about subsequent reads) requires some bookkeeping in the filesystem, because data which has been successfully "written" to a kernel buffer but not yet synched to disk must be made transparently available to processes reading from that file. This also requires some internal locking of kernel metadata.

由于写入常规文件通常是通过内核缓冲区完成的,并且实际上将数据同步到物理存储设备绝对不是 原子,因此提供这些保证所必需的锁不必非常高持久的.但是它们必须在文件系统内部完成,因为Posix措辞中的任何内容都不能保证对单个线程进程中的同时写入的保证.

Since writing to regular files is typically accomplished via kernel buffers and actually synching the data to the physical storage device is definitely not atomic, the locks necessary to provide these guarantee don't have to be very long-lasting. But they must be done inside the filesystem because nothing in the Posix wording limits the guarantees to simultaneous writes within a single threaded process.

在多线程进程中,Posix确实需要 read() write() pread() pwrite()在处理常规文件(或符号链接)时是原子的.请参阅与常规文件操作的线程交互,以获取完整的列表必须遵守此要求的接口.

Within a multithreaded process, Posix does require read(), write(), pread() and pwrite() to be atomic when they operate on regular files (or symbolic links). See Thread Interactions with Regular File Operations for a complete list of interfaces which must obey this requirement.

这篇关于unix原子中的写操作吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆