Согласованность двух потоков C FILE* в одном файле

Мне нужно реализовать простой слой "spill to disk" для большого объема данных, выходящих из сетевого сокета. Я надеялся получить два C FILE* потоки, один из которых используется фоновым потоком для записи в файл, а другой - внешним потоком, читающим его.

Эти два потока таковы, что один поток может писать с одним смещением, а другой - с другим, без блокировки и блокировки другого потока.

Будет механизм подкачки, поэтому операции чтения / записи будут в местах произвольного доступа - не обязательно последовательных.

Еще одно предостережение, это должно работать на Windows и Linux.

Вопрос: после возврата fwrite к первому потоку гарантированно ли эти записанные данные будут сразу же видны для фреда во втором потоке?

Если нет, какие еще варианты я мог бы рассмотреть?


Таким образом, функции preix /pwrite от Posix оказались именно тем, что мне нужно. Вот версия для 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;
}

(И спасибо всем за вклад в это - очень ценится).

2 ответа

Решение

Это определенно не даст вам семантику, которую вы хотите. Если вы отключили буферизацию, было бы разумно ожидать, что она будет работать, но я все еще не думаю, что есть какие-либо гарантии. STDIO /FILE это действительно не тот инструмент для специализированных нужд ввода-вывода, как это.

POSIX способ сделать то, что вы хотите, с помощью файловых дескрипторов и pread/pwrite функции. Я подозреваю, что есть способ Windows (или вы могли бы эмулировать их на основе какого-то другого базового примитива Windows), но я этого не знаю.

Кроме того, предложение Бена использовать IO с отображением в памяти является очень хорошим, если предположить, что файл помещается в ваше адресное пространство.

Это звучит как отлично подходит для ввода-вывода с отображением в памяти. Гарантируется, что он будет последовательным, очень быстрым, а отслеживание нескольких указателей будет простым.

Вам понадобятся разные функции для настройки отображения памяти в разных ОС, но реальный ввод / вывод полностью переносим (с использованием указателя).

  • Linux: open, mmap
  • Окна: CreateFileMapping, MapViewOfFile
Другие вопросы по тегам