Открыть сервис

Системный вызов sync

sync (от англ. synchronize — синхронизировать) — это системный вызов в операционных системах семейства Unix (включая Linux), предназначенный для принудительной записи всех изменённых, но ещё не сохранённых на постоянном носителе (например, жёстком диске или твердотельном накопителе) данных из буферов файловой системы (кэша) на устройство хранения. Вызов обеспечивает синхронизацию состояния файловой системы в оперативной памяти с её состоянием на диске, что критически важно для предотвращения потери данных при внезапном отключении питания, сбое ядра или аппаратном сбое.

Принцип работы

Современные операционные системы, включая ядро Linux, используют механизм кэширования для повышения производительности ввода-вывода. При записи данных в файл они сначала помещаются в оперативную память (в так называемый «страничный кэш» или «буферный кэш»), а затем асинхронно сбрасываются на диск фоновыми процессами (например, pdflush в Linux). Это позволяет приложению быстро завершить операцию записи, не дожидаясь медленного обращения к физическому устройству. Однако при сбое питания или аварийном завершении работы данные, находящиеся только в кэше, могут быть потеряны.

Системный вызов sync заставляет ядро немедленно начать сброс всех изменённых буферов на диск и дождаться завершения всех операций записи. После возврата из вызова гарантируется, что все данные, которые были записаны в файловую систему до этого момента, физически находятся на носителе. Вызов sync не принимает аргументов и не возвращает значения, указывающего на успех или неудачу (хотя в некоторых реализациях может возвращать 0 в случае успеха). Он действует на всю файловую систему целиком, а не на отдельный файл или каталог.

История

Системный вызов sync появился в самых ранних версиях операционной системы Unix, разработанной в Bell Labs (AT&T) в конце 1960-х — начале 1970-х годов. В то время компьютеры были менее надёжны, а сбои питания — обычным делом, поэтому необходимость в принудительной синхронизации данных была очевидна. В первой редакции Unix (1971 год) sync уже присутствовал как одна из основных системных функций. Впоследствии он был стандартизирован в рамках POSIX (Portable Operating System Interface) и стал обязательным элементом для всех Unix-подобных систем, включая Linux, FreeBSD, macOS и другие.

В Linux вызов sync реализован в ядре и документирован в разделе 2 руководства (man 2 sync). В более поздних версиях ядра (начиная с 2.6.33) появилась также системная функция syncfs(), которая синхронизирует данные только для одной указанной файловой системы, а не для всех смонтированных.

Связанные системные вызовы и утилиты

Помимо sync, существуют другие системные вызовы и утилиты, обеспечивающие синхронизацию данных на различных уровнях:

  • fsync() — синхронизирует только данные и метаданные одного конкретного файла, заданного файловым дескриптором. Более эффективен, чем sync, если требуется гарантировать сохранность только одного файла (например, базы данных или журнала транзакций).
  • fdatasync() — аналогичен fsync(), но синхронизирует только данные файла, не затрагивая метаданные (например, время последнего изменения), если это не влияет на целостность данных. Может быть быстрее.
  • syncfs() — синхронизирует все данные, относящиеся к одной файловой системе, смонтированной по указанному файловому дескриптору.
  • Утилита sync — командная программа, доступная в терминале, которая вызывает системный вызов sync (или syncfs() в некоторых реализациях). Используется администраторами для принудительной записи данных перед отключением устройства или выключением системы.
  • Утилита mount с опцией sync — при монтировании файловой системы с опцией sync (например, mount -o sync /dev/sda1 /mnt) все операции записи выполняются синхронно, без кэширования. Это снижает производительность, но гарантирует, что данные сразу записываются на диск. Используется для сменных носителей (флешек, внешних дисков), чтобы избежать потери данных при внезапном извлечении.

Применение

Системный вызов sync и связанные с ним утилиты применяются в следующих сценариях:

  1. Перед отключением питания или извлечением накопителя. При использовании съёмных устройств (USB-флешек, внешних дисков) рекомендуется выполнить команду sync перед физическим отключением, чтобы гарантировать, что все данные записаны. Однако современные операционные системы автоматически выполняют синхронизацию при размонтировании (umount), поэтому прямой вызов sync часто избыточен.
  2. В сценариях резервного копирования. Перед копированием данных на внешний носитель или в облачное хранилище может быть выполнен sync, чтобы убедиться, что исходные данные полностью сохранены на диске.
  3. В системах с повышенными требованиями к надёжности. Серверы баз данных, файловые серверы и критически важные приложения могут вызывать fsync() или fdatasync() после каждой транзакции, чтобы гарантировать целостность данных. Полный sync используется реже из-за его высокой стоимости по производительности (он блокирует всю систему ввода-вывода).
  4. В процедурах выключения и перезагрузки. Команды shutdown, reboot и halt в Unix-системах перед завершением работы вызывают sync для сохранения всех изменений. В Linux это делается автоматически.
  5. В тестировании и отладке. Разработчики файловых систем и драйверов устройств могут использовать sync для принудительного сброса кэша и проверки корректности работы после сбоев.

Производительность и ограничения

Вызов sync является дорогостоящей операцией, так как он блокирует выполнение всех процессов, пытающихся выполнить запись на диск, до завершения синхронизации. Время выполнения зависит от объёма данных в кэше, скорости диска и текущей нагрузки на подсистему ввода-вывода. В системах с большим количеством изменённых данных (например, при интенсивной записи) sync может занимать от нескольких секунд до нескольких минут.

Кроме того, sync не гарантирует, что данные будут записаны на физический носитель немедленно, если между диском и контроллером используется кэш записи самого устройства (например, на жёстких дисках с включённым кэшем). В таких случаях данные могут оставаться в кэше диска даже после возврата из sync. Для обхода этой проблемы в Linux существуют команды hdparm -W0 (отключение кэша записи на диске) или использование флага O_SYNC / O_DSYNC при открытии файла.

Безопасность и целостность данных

Системный вызов sync является важным инструментом для обеспечения целостности данных, но не является панацеей. В случае сбоя питания во время выполнения sync часть данных может быть потеряна, так как ядро не может гарантировать атомарность всей операции. Для критически важных приложений (например, баз данных) используются более сложные механизмы, такие как журналирование (журналируемые файловые системы, например, ext4, XFS, Btrfs) или транзакционные системы.

Реализация в различных операционных системах

  • Linux: вызов sync реализован в ядре и документирован в man 2 sync. В дополнение к нему существует syncfs(), а также утилита sync из пакета coreutils. В большинстве дистрибутивов Linux команда sync доступна по умолчанию.
  • FreeBSD: аналогичная реализация, также поддерживается syncfs(). Утилита sync входит в базовую систему.
  • macOS: системный вызов sync присутствует, но его поведение может отличаться из-за особенностей файловой системы HFS+ или APFS. Утилита sync доступна в терминале.
  • Windows: в операционных системах семейства Windows нет прямого аналога sync, но существуют функции Win32 API, такие как FlushFileBuffers() (для одного файла) и FlushViewOfFile() (для отображённых в память файлов). Команда sync отсутствует; для принудительной записи данных используется fsutil или вызовы API.

Интересные факты

  • В ранних версиях Unix команда sync выполнялась дважды подряд, так как первый вызов мог инициировать запись, а второй гарантировал её завершение. В современных системах это не требуется.
  • В некоторых реализациях (например, в Linux) вызов sync может быть прерван сигналом, что может привести к частичной записи данных.
  • В ядре Linux существует системный вызов sync_file_range(), который позволяет синхронизировать только определённый диапазон байт внутри файла, что даёт более тонкий контроль над производительностью.

Источники

  • man-страницы: sync(2), fsync(2), fdatasync(2), syncfs(2), sync(8) (Linux).
  • Спецификация POSIX.1-2017, раздел «sync».
  • «The Design of the UNIX Operating System» by Maurice J. Bach (1986).
  • «Linux Kernel Development» by Robert Love (3rd edition, 2010).
  • Документация ядра Linux: Documentation/filesystems/.

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →