Одновременная запись в файл с использованием нескольких потоков
У меня есть программа уровня пользователя, которая открывает файл, используя флаги O_WRONLY|O_SYNC
, Программа создает 256 потоков, которые пытаются записать 256 или более байтов данных каждый в файл. Я хочу получить 1280000 запросов, что составляет около 300 МБ данных. Программа заканчивается, как только 1280000 запросов были выполнены.
я использую pthread_spin_trylock()
увеличить переменную, которая отслеживает количество запросов, которые были выполнены. Чтобы убедиться, что каждый поток записывает в уникальное смещение, я использую pwrite()
и рассчитать смещение как функцию количества уже написанных запросов. Следовательно, я не использую мьютекс при записи в файл (обеспечивает ли этот подход целостность данных?)
Когда я проверяю среднее время, за которое pwrite()
вызов был заблокирован и соответствующие номера (т.е. среднее время Q2C - которое является мерой времени для полного жизненного цикла BIO), как было найдено с использованием blktrace
Я считаю, что есть существенная разница. Фактически, среднее время завершения для данной BIO намного больше, чем средняя задержка pwrite()
вызов. В чем причина этого несоответствия? Разве эти цифры не должны быть похожи, так как O_SYNC
гарантирует, что данные действительно записаны на физический носитель перед возвратом?
1 ответ
pwrite()
это должно быть атомно, так что вы должны быть в безопасности там...
Что касается разницы в задержке между вашим системным вызовом и фактическим BIO, согласно этой информации на man-страницах на 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
Пометить всю информацию, которую вы пытаетесь записать, не нужно записывать на диск перед возвратом системного вызова, а просто достаточно информации, чтобы можно было извлечь ее с диска... в зависимости от того, что вы пишете, что может быть немного меньше, чем весь буфер данных, который вы намеревались записать на диск, и, следовательно, фактическая запись всех данных будет происходить позднее, после того, как системный вызов завершен и процесс переместится на что-то другое.