【发布时间】:2011-09-27 06:26:25
【问题描述】:
我正在用 C++ 编写代码。我会遇到任何类型的竞争条件或段错误吗?
【问题讨论】:
-
如果您需要非顺序的并发文件访问,我建议您改用内存映射文件。然后将其视为普通内存并进行自己的锁定(如果您可以保证写入/读取位置不重叠,则不需要)。
标签: c++
我正在用 C++ 编写代码。我会遇到任何类型的竞争条件或段错误吗?
【问题讨论】:
标签: c++
从底层系统的角度来看,这样做没有问题(对于我所知道的所有系统)。但是,通常您需要完全独立的文件描述符/句柄。这是因为文件描述符保持状态,例如当前文件位置。
您还需要检查您正在使用的文件系统的特定 C++ 接口的线程安全性。除了底层文件系统的线程安全之外,这也是必需的。
您还应该考虑线程 I/O 会变慢的可能性。系统可能必须串行访问总线。您可以从重叠 I/O 或通过生产者/消费者管道馈送的专用 I/O 线程获得更好的性能。
【讨论】:
根据文件大小和您运行的系统,另一种解决方案是使用memory mapped files,即。将文件映射到虚拟内存。这将使您可以直接访问文件,就好像它是一块内存一样。这样,任意数量的线程都可以简单地写入内存区域,随后调用将映射刷新到磁盘(取决于您的内存映射配置)将简单地将数据存储在磁盘上。
请注意,由于 32 位平台的地址限制,您无法映射任何大于通常 2-3 GB 的文件,具体取决于架构和可用于执行虚拟内存的实际位数寻址。大多数 64 位系统都有 48 位或更多可用于此任务,允许您映射至少 256 TB,我认为这绰绰有余。
【讨论】:
mmap 函数支持内存映射。 man 页面提供了更多详细信息,在您的情况下为like this。通常,所需的步骤只是打开一个文件描述符,必要时预分配它的大小(手动或通过 fallocate 或 posix_fallocate),然后将其映射到内存,一切顺利。
这取决于。 文件不是它们的句柄,流也不是文件。 这三个不同的概念一定要搞清楚。
现在,操作系统可以多次打开文件,返回不同的句柄,每个句柄都有自己的“位置指针”。如果文件以“共享模式”打开以进行读取和写入,您可以在所需的位置查找句柄并根据需要进行读取/写入。您不覆盖的事实取决于您。系统为整个文件或部分文件授予操作的顺序性(但需要有关操作系统的更多信息)
如果每个句柄都附加到不同的流,则每个流将独立于另一个写入。但是 - 在这种情况下 - 存在“缓冲”的复杂性(写入可以延迟并且可以预期读取:并且可以根据您的要求更长:确保通过适当的刷新来正确管理最终的重叠)
【讨论】:
当然可以。根据您编写实际代码的方式(即使用该文件),可能会出现竞争条件。此外,如果 IO 被缓冲,如果缓冲区域重叠,可能会出现奇怪的事情。
【讨论】: