_sopen_s 如何管理对同一文件的多次写入
How does _sopen_s manage multiple writing to same file
我有一个 C++ 应用程序可以处理多个连接并写入文件。当使用带有参数 _SH_DENYNO
的函数 _sopen_s
时,所有同时工作的线程都在写入文件,我没有看到数据丢失。您能告诉我该函数如何管理对文件的访问,从而不会丢失数据吗?
亲切的问候
如果您正在使用 write()
或它的某些 OS 提供的变体,则往往会实现单独的 write()
调用,以便每次调用 write()
是原子的,因为这个 POSIX statement regarding write()
:
On a regular file or other file capable of seeking, the actual writing
of data shall proceed from the position in the file indicated by the
file offset associated with fildes. Before successful return from
write(), the file offset shall be incremented by the number of bytes
actually written. On a regular file, if this incremented file offset
is greater than the length of the file, the length of the file shall
be set to this file offset.
这有点难以以允许来自对同一文件描述符的单独 write()
调用的交错数据的方式实现,因为如果数据是交错的,则完成后文件偏移量的变化将不相等到 "number of bytes actually written"。因此,该语句可以解释为对任何 "regular file or other file capable of seeking".
上的 write()
调用的原子性的隐含要求
此外,还有一个明确的 POSIX requirement,即 write()
对小于或等于 PIPE_BUF
字节的管道的调用是原子的:
Atomic/non-atomic: A write is atomic if the whole amount written in one operation is not interleaved with data from any other process.
This is useful when there are multiple writers sending data to a
single reader. Applications need to know how large a write request can
be expected to be performed atomically. This maximum is called
{PIPE_BUF}. This volume of POSIX.1-2008 does not say whether write
requests for more than {PIPE_BUF} bytes are atomic, but requires that
writes of {PIPE_BUF} or fewer bytes shall be atomic.
因为 write()
只是得到一个文件描述符的 int
而没有其他直接可用的关于文件描述符所指内容的信息,所以最简单的实现 write()
的方法是满足管道原子 write()
的 POSIX 要求的方法是使每个 write()
调用原子。
因此,虽然没有要求 原子性,除非您向实际管道写入少于或等于 PIPE_BUF
字节,write()
倾向于以原子方式实现所有内容。
现在,这并不意味着无论文件描述符指向什么,都不会分解数据或将其与其他数据交错。例如,如果两个线程各自尝试调用一个 write()
操作以将数 GB 的数据从 MPEG 文件同时流式传输到同一个 TCP 套接字,那么看到交错数据我一点也不会感到惊讶。
而且您实际上并不是在调用 write()
。但底层实现可能是共享的。
我有一个 C++ 应用程序可以处理多个连接并写入文件。当使用带有参数 _SH_DENYNO
的函数 _sopen_s
时,所有同时工作的线程都在写入文件,我没有看到数据丢失。您能告诉我该函数如何管理对文件的访问,从而不会丢失数据吗?
亲切的问候
如果您正在使用 write()
或它的某些 OS 提供的变体,则往往会实现单独的 write()
调用,以便每次调用 write()
是原子的,因为这个 POSIX statement regarding write()
:
On a regular file or other file capable of seeking, the actual writing of data shall proceed from the position in the file indicated by the file offset associated with fildes. Before successful return from write(), the file offset shall be incremented by the number of bytes actually written. On a regular file, if this incremented file offset is greater than the length of the file, the length of the file shall be set to this file offset.
这有点难以以允许来自对同一文件描述符的单独 write()
调用的交错数据的方式实现,因为如果数据是交错的,则完成后文件偏移量的变化将不相等到 "number of bytes actually written"。因此,该语句可以解释为对任何 "regular file or other file capable of seeking".
write()
调用的原子性的隐含要求
此外,还有一个明确的 POSIX requirement,即 write()
对小于或等于 PIPE_BUF
字节的管道的调用是原子的:
Atomic/non-atomic: A write is atomic if the whole amount written in one operation is not interleaved with data from any other process. This is useful when there are multiple writers sending data to a single reader. Applications need to know how large a write request can be expected to be performed atomically. This maximum is called {PIPE_BUF}. This volume of POSIX.1-2008 does not say whether write requests for more than {PIPE_BUF} bytes are atomic, but requires that writes of {PIPE_BUF} or fewer bytes shall be atomic.
因为 write()
只是得到一个文件描述符的 int
而没有其他直接可用的关于文件描述符所指内容的信息,所以最简单的实现 write()
的方法是满足管道原子 write()
的 POSIX 要求的方法是使每个 write()
调用原子。
因此,虽然没有要求 原子性,除非您向实际管道写入少于或等于 PIPE_BUF
字节,write()
倾向于以原子方式实现所有内容。
现在,这并不意味着无论文件描述符指向什么,都不会分解数据或将其与其他数据交错。例如,如果两个线程各自尝试调用一个 write()
操作以将数 GB 的数据从 MPEG 文件同时流式传输到同一个 TCP 套接字,那么看到交错数据我一点也不会感到惊讶。
而且您实际上并不是在调用 write()
。但底层实现可能是共享的。