TGViewer
BashTex | Linux BashTex | Linux @bash_tex · 2.52K subscribers
Post #660 324
flock vs fcntl - почему две блокировки одного файла могут вести себя совершенно по-разному

В Linux есть несколько механизмов блокировки файлов. Наиболее часто встречаются flock() и fcntl().

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

▪️flock блокирует сам файл

Простейший вариант:

flock /tmp/app.lock -c 'echo "working"; sleep 10'


Пока первый процесс держит блокировку, второй:

flock -n /tmp/app.lock -c 'echo "working"'


получит ошибку и сразу завершится из-за -n.
Часто этот механизм используют для защиты cron-задач:

flock -n /run/myjob.lock /usr/local/bin/myjob


▪️fcntl работает через диапазоны файла
Здесь можно блокировать не только весь файл, но и конкретный диапазон байтов.

На уровне C:

struct flock lock = {
.l_type = F_WRLCK,
.l_whence = SEEK_SET,
.l_start = 0,
.l_len = 100
};

fcntl(fd, F_SETLK, &lock);


Можно заблокировать первые 100 байт, а другой процесс при этом сможет работать с другим диапазоном.

▪️Главная ловушка

Процесс A:

flock /tmp/test.lock


Процесс B использует fcntl() для того же файла.

Они не обязаны конфликтовать.

Причина в том, что flock и традиционные POSIX advisory locks через fcntl исторически используют разные пространства блокировок.
То есть наличие:

flock → locked


не означает автоматически:

fcntl → blocked


И наоборот.

▪️Обе блокировки advisory

Ни flock, ни fcntl сами по себе не запрещают процессу открыть и изменить файл.

Если приложение вообще не проверяет блокировку, оно может спокойно сделать:

echo "data" >> /tmp/file


Поэтому механизм работает только тогда, когда все участники системы договариваются его соблюдать.

▪️Есть ещё одна важная разница

Для flock блокировка связана с открытым file description. При fork() дочерний процесс наследует соответствующую блокировку.

У fcntl семантика другая: POSIX locks связаны с процессом и имеют собственные правила поведения при close().

Из-за этого без понимания модели владения FD легко получить ситуацию, когда один close() неожиданно освобождает блокировку.

▪️Практический вывод
Если нужно просто гарантировать, что cron или несколько экземпляров shell-скрипта не выполняются одновременно:

flock -n /run/myjob.lock /usr/local/bin/myjob


обычно достаточно.

Если приложение должно блокировать отдельные диапазоны файла или ему нужна POSIX-модель блокировок, используют fcntl().

И главное: нельзя считать flock и fcntl взаимозаменяемыми только потому, что оба называются file locking.

BashTex 📱 #bash #utils
  • 👍 6
More from @bash_tex
  1. Oct 6, 2026Ephemeral ports - почему заканчиваются исходящие TCP-порты Когда приложение устанавливает…
  2. Oct 5, 2026name_to_handle_at() - как получить файловый объект без обычного пути В Linux обычно обраща…
  3. Oct 2, 2026madvise() - как процесс подсказывает ядру, как он собирается использовать память Когда про…
  4. Sep 30, 2026DEBUG trap - как Bash выполняет код перед каждой командой В Bash есть специальный DEBUG tr…
  5. Sep 29, 2026tee + process substitution: один поток и несколько получателей Иногда нужно одновременно:…
  6. Sep 28, 2026Архитектура большого bash-скрипта Пока скрипт на 30 строк - все терпимо. На 300 строк начи…
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 →