Согласованность двух потоков 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