Подтвердить что ты не робот

Unix читает и записывает в один файл с атомной сериализацией?

Я хотел бы знать, если записи по одному файлу выполняются атомарно, так что запись ( "bla bla" ) и последующая запись ( "herp derp" ) в один и тот же файл никогда не приводят к перемежению, например. "bla herp bla derp". Предполагая, что эти записи происходят в разных процессах или потоках, что определяет, что происходит сначала?

Также, read() всегда возвращает данные, отражающие файл в состоянии всех предыдущих записей, полностью завершенных (независимо от того, были ли данные записаны на диск или нет)? Например, после записи ( "herp derp" ) все последующие чтения всегда будут отражать полные данные, записанные в файл, или последующее чтение иногда отражает только "herp", но не "derp" (или иногда не отражает ни одну из данных вообще)? Что делать, если чтения и записи происходят в разных процессах/потоках?

Мне не интересны параллельные стратегии доступа к файлам. Я просто хочу знать, что читать и писать делать точно.

4b9b3361

Ответ 1

Отдельные вызовы write() обрабатываются отдельно, а не как одна транзакция атомарной записи, а чередование возможно, когда несколько процессов/потоков записываются в один и тот же файл. Порядок фактической записи определяется планировщиками (как планировщик процесса ядра, так и "зелеными" потоками - планировщик библиотеки потоков).

Если вы не указали иначе (O_DIRECT open флаг или аналогичный, если поддерживается), read() и write() работают с буферами ядра, а read() будет использовать загруженный буфер, предпочитая снова читать диск.

Обратите внимание, что это может быть осложнено локальной файловой буферизацией; например, stdio и iostreams будут считывать данные файла по блокам в буфер в процессе, который не зависит от буферов ядра, поэтому write() из другого места в данные, которые уже буферизованы в stdio, не будет видел. Аналогично, с буферизацией вывода не будет никакого фактического вывода уровня ядра до тех пор, пока выходной буфер не будет сброшен, либо автоматически, потому что он заполнил или вручную из-за fflush() или С++ endl (который неявно очищает выходной буфер).