2

我需要为来自网络套接字的大量数据实现一个简单的“溢出到磁盘”层。我希望有两个 CFILE*流,一个由写入文件的后台线程使用,一个由读取它的前端线程使用。

这两个流是这样一个线程可以在一个偏移量处写入,而另一个在其他地方读取 - 无需锁定并阻塞另一个线程。

将有一个分页机制,因此读/写是在随机访问位置 - 不一定是顺序的。

还有一点需要注意的是,这需要在 Windows 和 Linux 上运行。

问题:在第一个流的 fwrite 返回后,写入的数据是否保证对第二个流上的 fread 立即可见?

如果没有,我还可以考虑哪些其他选择?


所以 Posix 的 pread/pwrite 函数结果是我需要的。这是 Win32 的版本:

size_t pread64(int fd, void* buf, size_t nbytes, __int64 offset)
{
    OVERLAPPED ovl;
    memset(&ovl, 0, sizeof(ovl));
    *((__int64*)&ovl.Offset)=offset;

    DWORD nBytesRead;
    if (!ReadFile((HANDLE)_get_osfhandle(fd), buf, nbytes, &nBytesRead, &ovl))
        return -1;

    return nBytesRead;
}

size_t pwrite64(int fd, void* buf, size_t nbytes, __int64 offset)
{
    OVERLAPPED ovl;
    memset(&ovl, 0, sizeof(ovl));
    *((__int64*)&ovl.Offset)=offset;

    DWORD nBytesWritten;
    if (!WriteFile((HANDLE)_get_osfhandle(fd), buf, nbytes, &nBytesWritten, &ovl))
        return -1;

    return nBytesWritten;
}

(感谢大家对此的投入 - 非常感谢)。

4

2 回答 2

4

这听起来非常适合内存映射 I/O。它保证是连贯的、非常快的,并且跟踪多个指针很简单。

您需要不同的函数来在不同的操作系统上设置内存映射,但实际的 I/O 是完全可移植的(使用指针引用)。

  • linux: open,mmap
  • 窗户:CreateFileMappingMapViewOfFile
于 2011-03-10T02:02:16.277 回答
2

这绝对不会给你你想要的语义。如果您禁用缓冲,期望它工作可能是合理的,但我仍然认为没有任何保证。Stdio/FILE真的不是像这样专门的 IO 需求的正确工具。

使用文件描述符和pread/pwrite函数来做你想做的事情的 POSIX 方法。我怀疑有一种 Windows 方式(或者您可以基于其他一些底层 Windows 原语来模拟它们),但我不知道。

假设文件适合您的地址空间,Ben 的使用内存映射 IO 的建议也是一个非常好的建议。

于 2011-03-10T02:12:20.567 回答