Вызов fsync() возвращает управление только после завершения переноса данных на дисковое устройство (или по крайней мере в его кэш-память).
#include
int fsync(int
Возвращает при успешном завершении 0 или –1 при ошибке
Системный вызов fdatasync() работает точно так же, как и fsync(), но приводит файл в состояние целостности (данных) после после завершения синхронного ввода-вывода.
#include
int fdatasync(int
Возвращает при успешном завершении 0 или –1 при ошибке
Использование fdatasync() потенциально сокращает количество дисковых операций с двух, необходимых системному вызову fsync(), до одного. Например, если данные файла изменились, но размер остался прежним, вызов fdatasync() вызывает лишь принудительное обновление данных. (Выше уже отмечалось, что для завершения синхронной операции ввода-вывода с целостностью данных нет необходимости переносить изменение таких аттрибутов, как время последней модификации файла.) В отличие от этого вызов fsync() приведет также к принудительному переносу на диск метаданных.
Такое сокращение количества дисковых операций ввода-вывода будет полезным для отдельных приложений, для которых решающую роль играет производительность и неважно аккуратное обновление конкретных метаданных (например, отметок времени). Это может привести к существенным улучшениям производительности приложений, производящих несколько обновлений файла за раз. Поскольку данные и метаданные файла обычно располагаются в разных частях диска, обновление и тех и других потребует повторяющихся операций поиска вперед и назад по диску.
В Linux 2.2 и более ранних версиях fdatasync() реализован в виде вызова fsync(), поэтому не дает никакого прироста производительности.
Начиная с ядра версии 2.6.17, в Linux предоставляется нестандартный системный вызов sync_file_range(). Он позволяет более точно управлять процессом сброса данных файла на диск, чем fdatasync(). При вызове можно указать сбрасываемую область файла и задать флаги, устанавливающие условия блокировки данного вызова. Дополнительные подробности вы найдете на странице руководства sync_file_range(2).
Системный вызов sync() приводит к тому, что все буферы ядра, содержащие обновленную файловую информацию (то есть блоки данных, блоки указателей, метаданные и т. д.), сбрасываются на диск.
#include
void sync(void);
В реализации Linux функция sync() возвращает управление только после того, как все данные будут перенесены на дисковое устройство (или как минимум в его кэш-память). Но в SUSv3 разрешается, чтобы sync() просто вносила в план перенос данных для операции ввода-вывода и возвращала управление до завершения этого переноса.
Постоянно выполняемый поток ядра обеспечивает сброс измененных буферов ядра на диск, если они не были явным образом синхронизированы в течение 30 секунд. Это делается для того, чтобы не допустить рассинхронизации данных буферов с соответствующим дисковым файлом на длительные периоды времени (и не подвергнуть их риску утраты при отказе системы). В Linux 2.6 эта задача выполняется потоком ядра pdflush. (В Linux 2.4 она выполнялась потоком ядра kupdated.)
Срок (в сотых долях секунды), через который измененный буфер должен быть сброшен на диск кодом потока pdflush, определяется в файле /proc/sys/vm/dirty_expire_centisecs. Дополнительные файлы в том же самом каталоге управляют другими особенностями операции, выполняемой потоком pdflush.
Указание флага O_SYNC при вызове open() приводит к тому, что все последующие операции вывода выполняются в синхронном режиме:
fd = open(
После этого вызова open() каждая проводимая с файлом операция write() автоматически сбрасывает данные и метаданные файла на диск (то есть записи выполняются как синхронизированные операции записи с целостностью файла).
В старых версиях системы BSD для обеспечения функциональных возможностей, включаемых флагом O_SYNC, использовался флаг O_FSYNC. В glibc флаг O_FSYNC определен как синоним O_SYNC.
Использование флага O_SYNC (или же частые вызовы fsync(), fdatasync() или sync()) может сильно повлиять на производительность. В табл. 13.3 показано время, требуемое для записи 1 миллиона байт в только что созданный файл (в файловой системе ext2) при различных размерах буфера с выставленным и со сброшенным флагом O_SYNC. Результаты были получены (с помощью программы filebuff/write_bytes.c, предоставляемой в исходном коде для книги) с использованием «ванильного» ядра версии 2.6.30 и файловой системы ext2 с размером блока 4096 байт. В каждой строке приводится усредненное значение, полученное после 20 запусков для заданного размера буфера.
Таблица 13.3. Влияние флага O_SYNC на скорость записи 1 миллиона байт
BUF_SIZE
Требуемое время (в секундах)
Без использования O_SYNC