TGViewer
BashTex | Linux BashTex | Linux @bash_tex · 2.51K subscribers
Post #670 78
fsync() vs fdatasync(): когда данные действительно попадают на диск

Программа записала данные в файл, write() вернул успешный результат. Кажется, всё сохранилось.

Но если в этот момент отключить питание, часть данных может исчезнуть. Причина в том, что успешный write() ещё не означает запись на физический носитель.

▪️Куда попадают данные после write()

Обычно Linux сначала помещает изменения в page cache - область оперативной памяти, используемую для кеширования файлов.

write()
↓
page cache
↓
writeback
↓
накопитель


Ядро самостоятельно решает, когда отправлять изменённые страницы на диск.

Это ускоряет работу, но создаёт промежуток между успешной записью и её сохранением на носителе.

▪️Что делает fsync()
Вызов:

fsync(fd);


запрашивает запись изменённых данных файла и связанных с ним метаданных, необходимых для синхронизации.
Например, программа обновила файл конфигурации. Чтобы не полагаться на фоновый writeback, она может вызвать fsync() после записи.

write(fd, data, size);

if (fsync(fd) == -1) {
perror("fsync");
}


Если вызов завершился успешно, ядро выполнило требуемую синхронизацию файла с устройством хранения.

▪️Чем отличается fdatasync()

fdatasync(fd);

Этот вызов тоже синхронизирует данные, но не обязан записывать все изменения метаданных.

Например, изменение времени модификации файла само по себе не требует синхронизации через fdatasync().

Но если файл увеличился, новый размер необходимо сохранить: без него записанные данные могут оказаться недоступными после сбоя.

Поэтому fdatasync() не означает «записать только содержимое и забыть обо всём остальном».

▪️Что быстрее?

fdatasync() потенциально быстрее, потому что может выполнять меньше операций с метаданными.

Но разница зависит от файловой системы, накопителя и характера записи. Иногда оба вызова приводят практически к одинаковой работе.

▪️Важный нюанс с rename()

Допустим, приложение безопасно обновляет конфигурацию:

1. Создаёт config.tmp
2. Записывает новые данные
3. Вызывает fsync(config.tmp)
4. Переименовывает в config.json


Этого недостаточно, чтобы гарантировать сохранность самого переименования после сбоя.

Для этого обычно требуется дополнительно вызвать fsync() на файловом дескрипторе родительского каталога.

И ещё: даже успешный fsync() зависит от того, насколько корректно накопитель выполняет команды сброса кеша.

▪️Почему это важно

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

fsync() синхронизирует данные и связанные метаданные файла, а fdatasync() может пропустить метаданные, не нужные для последующего чтения данных.

Разница особенно важна для баз данных, журналов транзакций и приложений, которым нельзя терять подтверждённые записи.

BashTex 📱 #bash #linux
  • 🔥 3
  • 👍 1
More from @bash_tex
  1. Oct 14, 2026coproc: как Bash общается с фоновым процессом в обе стороны Обычно Bash запускает фоновый…
  2. Oct 13, 2026openat2(): как Linux защищает от выхода за пределы каталога Допустим, приложение должно чи…
  3. Oct 12, 2026xargs против while read: где быстрее и безопаснее Обе конструкции позволяют обработать спи…
  4. Oct 9, 2026BashTex 📱 #мем
  5. Oct 8, 2026Bridge FDB - как Linux bridge узнаёт, где находится MAC Linux bridge не знает заранее, за…
  6. Oct 7, 2026/dev/tcp - сетевое соединение средствами Bash В Bash есть малоизвестная возможность работа…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →