Одновременная запись в файл с использованием нескольких потоков - PullRequest
4 голосов
/ 25 августа 2011

У меня есть программа уровня пользователя, которая открывает файл с помощью флагов O_WRONLY|O_SYNC. Программа создает 256 потоков, которые пытаются записать 256 или более байтов данных каждый в файл. Я хочу получить 1280000 запросов, что составляет около 300 МБ данных. Программа заканчивается, когда 1280000 запросов были выполнены.

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

Когда я проверяю среднее время, в течение которого звонок pwrite() был заблокирован, и соответствующие номера (т. Е. Среднее время Q2C - которое является мерой времени для полного жизненного цикла BIO), найденное с использованием blktrace, я считаю, что есть существенная разница. Фактически, среднее время завершения для данного BIO намного больше, чем средняя задержка вызова pwrite(). В чем причина этого несоответствия? Разве эти числа не должны быть похожими, поскольку O_SYNC гарантирует, что данные действительно записываются на физический носитель перед возвратом?

1 Ответ

3 голосов
/ 25 августа 2011

pwrite() предполагается, что он атомарный, поэтому вы должны быть в безопасности ...

Что касается разницы в задержке между вашим системным вызовом и фактическим BIO, согласно этой информации на man-pages на kernel.org для open (2):

POSIX предоставляет три различных варианта синхронизированного ввода-вывода, соответствующих флагам O_SYNC, O_DSYNC и O_RSYNC.В настоящее время (2.6.31) Linux реализует только O_SYNC, но glibc отображает O_DSYNC и O_RSYNC в то же числовое значение, что и O_SYNC.Большинство файловых систем Linux на самом деле не реализуют семантику POSIX O_SYNC, которая требует, чтобы все обновления метаданных записи были на диске при возврате в пространство пользователя, а только семантику O_DSYNC, для которой требуются только фактические данные файла и метаданные, необходимые для его извлечения.быть на диске ко времени возврата системного вызова.

Таким образом, это в основном подразумевает, что с флагом O_SYNC вся информация, которую вы пытаетесь записать, не должна быть сброшена на дискперед возвратом системного вызова, но достаточно информации, достаточной для извлечения ее с диска ... в зависимости от того, что вы пишете, это может быть немного меньше, чем весь буфер данных, которым вы былинамереваясь записать на диск, и, следовательно, фактическая запись всех данных произойдет позже, после того, как системный вызов будет завершен, и процесс перейдет к чему-то другому.

...