- Введение в блокировку файлов в Linux
- 2. Проблема промежуточного обновления
- 3. Блокировка файлов в Linux
- 3.1. Консультативная блокировка
- 3.2. Обязательная блокировка
- 4. Проверка всех блокировок в системе
- 4.1. Команда lslocks
- 4.2. /proc/locks
- 5. Введение в команду flock
- 5.1. Демонстрация flock с некооперативными процессами
- 5.2. Демонстрация flock с кооперативными процессами
- 6. Заключение
Введение в блокировку файлов в Linux
Блокировка файлов – это механизм взаимного исключения, гарантирующий, что файл может быть прочитан/записан несколькими процессами безопасным способом.
В этом руководстве мы поймем проблему промежуточного обновления в системе с несколькими процессами. Затем мы собираемся представить два типа блокировок в Linux.
Попутно мы изучим некоторые команды, связанные с блокировкой файлов, на примерах.
2. Проблема промежуточного обновления
Промежуточное обновление – это типичная проблема состояния гонки в параллельной системе . Давайте посмотрим на пример, чтобы лучше понять проблему.
Допустим, у нас есть файл balance.dat , в котором хранится баланс учетной записи, и он имеет начальное значение из « 100 «. В нашей параллельной системе есть два процесса для обновления значения баланса:
- Процесс A: считывает текущее значение, вычитает 20 и сохраняет результат обратно в файл.
- Процесс B: считывает текущее значение, добавляет 80 и записывает результат обратно в файл.
Очевидно, что после выполнения двух процессов мы ожидаем файл имеет значение: 100-20+80=160.
Однако в этой ситуации может возникнуть промежуточная проблема обновления:
- Процесс A считывает текущее значение файла ( 100 ) и готовится к дальнейшим вычислениям.
- Процесс B теперь читает тот же файл и получает текущий баланс ( 100 ).
- Процесс A вычисляет 100-20 и сохраняет результат 80 обратно к файлу.
- Процесс B не знает, что баланс был обновлен с момента последнего чтения. Таким образом, он по-прежнему будет использовать устаревшее значение 100 для вычисления 100 + 80 и записи результата 180 в файл. .
В результате мы имеем 180 в файле balance.dat вместо ожидаемого значения 160.
3. Блокировка файлов в Linux
Блокировка файлов – это механизм ограничения доступа к файлу для нескольких процессов. Он позволяет только одному процессу получить доступ к файлу в определенное время , что позволяет избежать проблемы промежуточного обновления.
Все мы знаем, что rm – rf/ – очень опасная команда в Linux. Если мы выполним команду как пользователь root , все файлы в работающей системе будут удалены. Это связано с тем, что Linux обычно не блокирует открытые файлы автоматически. Однако Linux поддерживает два вида блокировок файлов: рекомендательные блокировки и обязательные блокировки.
Вскоре мы представим оба типа блокировки, но в этой статье основное внимание будет уделено рекомендательной блокировке. р>
3.1. Консультативная блокировка
Консультативная блокировка не является принудительной схемой блокировки. Это будет работать, только если участвующие процессы взаимодействуют, явно устанавливая блокировки. В противном случае рекомендательные блокировки будут игнорироваться, если процесс вообще не знает о блокировках..
Пример может помочь нам легче понять схему совместной блокировки. Давайте рассмотрим наш предыдущий пример баланса.
- Во-первых, мы предполагаем, что файл balance.dat все еще содержит начальное значение « 100 “.
- Процесс A устанавливает исключительную блокировку файла balance.dat , затем открывает и читает файл, чтобы получить текущую value: 100.
Мы должны понимать, что консультативная блокировка не была установлена операционной системой или файловой системой. Следовательно, даже если процесс A блокирует файл, процесс B по-прежнему может читать, записывать или даже удалять файл с помощью системных вызовов.
Если процесс B выполняет файловые операции, не пытаясь получить блокировку, мы говорим, что процесс B не взаимодействует с процессом A.
Но теперь давайте взглянем на как блокировка будет работать для взаимодействующих процессов :
- Процесс B пытается получить блокировку на balance.dat перед чтением файла (взаимодействуя с процессом A).
- Поскольку процесс A заблокировал файл, процесс B должен ждать, пока процесс A снимет блокировку.
- Процесс A вычисляет 100-20 и записывает 80 обратно в файл.
- Процесс A снимает блокировку.
- Теперь процесс B получает блокировку и читает файл, получая обновленное значение: 80.
- Процесс B запускает свою логику и записывает результат 160 ( 80 + 80 ) обратно в файл.
- Процесс B снимает блокировку, чтобы другие взаимодействующие процессы могли читать и писать в файл.
Мы увидим, как этот пример реализуется с помощью flock в следующем разделе.
3.2. Обязательная блокировка
Прежде чем мы начнем рассматривать обязательную блокировку файлов, мы должны помнить, что « реализация принудительной блокировки в Linux ненадежна «.
В отличие от рекомендательной блокировки, обязательная блокировка не требует какого-либо взаимодействия между участвующими процессами. После активации принудительной блокировки файла операционная система запрещает другим процессам читать или записывать файл.
Чтобы включить принудительную блокировку файлов в Linux, необходимо выполнить два требования:
- Мы должны смонтировать файловую систему с параметром mand ( mount – o mand FILESYSTEM MOUNT_POINT ).
- Мы должны включить бит set-group-ID и выключить бит выполнения группы для файлов, которые мы собираемся заблокировать ( chmod g + s, gx FILE ).
4. Проверка всех блокировок в системе
В этом разделе давайте рассмотрим два способа проверки текущих блокировок в работающей системе.
4.1. Команда lslocks
Команда lslocks является членом util-linux и доступен во всех дистрибутивах Linux. Он может перечислить все текущие блокировки файлов в нашей системе.
Давайте посмотрим на пример вывода:
$ lslocksCOMMAND PID TYPE SIZE MODE M START END PATHlvmetad 298 POSIX 4B WRITE 0 0 0/run/lvmetad .pidcontainerd 665 FLOCK 128K ЗАПИСАТЬ 0 0 0/var/lib/docker/. chromium 184029 POSIX 9.4M WRITE 0 1073741824 1073742335/home/kent/.config/chromium/Default/Historynextcloud 961 POSIX 32K READ 0 128 128/home /kent/Nextcloud/._sync_0e131dbf228b.db-shmdockerd 630 FLOCK 16K WRITE 0 0 0/var/lib/docker/buildkit/snapshots.dbdropbox 369159 FLOCK 10M WRITE 0 0 0/home/kent/1/1.dropbox/logs -4ede-5e20dd8d.tmp .
В приведенном выше списке мы можем увидеть все заблокированные в настоящее время файлы в системе. Мы также можем видеть подробную информацию о каждой блокировке, такую как тип блокировки и какой процесс удерживает блокировку.
4.2. /proc/locks
/proc/locks не является командой. Вместо этого это файл в виртуальной файловой системе procfs . Файл содержит все текущие блокировки файлов. Команда lslocks также использует этот файл для создания списка.
Чтобы получить информацию о /proc/locks , мы выполняем « cat/proc/locks »:
$ cat/proc/locks1: FLOCK ADVISORY WRITE 369159 08: 12: 22417368 0 EOF2: POSIX ADVISORY WRITE 321130 00: 2e: 30761 0 EOF3: POSIX ADVISORY WRITE 184029 08: 12: 21760394 0 EOF4: POSIX ADVISORY WRITE 184029 08: 12: 21633968 1073741824 10737423355ISO: POSIX 18408: POSIX ADVISO08: POSIX 214029: POSIX 21405 : POSIX ADVISORY WRITE 184029 08: 12: 21891515 0 EOF7: POSIX ADVISORY WRITE 184029 08: 12: 21633928 0 EOF .
Давайте выберем первую строку, чтобы понять, как блокируется информация организована в файловой системе /proc/locks :
1: FLOCK ADVISORY WRITE 369159 08: 12: 22417368 0 EOF-1 - --2-- --- 3 --- --4-- --- 5-- ------- 6 ------ -7- -8-
- Первый столбец – это порядковый номер.
- Второе поле указывает класс используемой блокировки, например FLOCK ( из системного вызова flock ) или POSIX (из системного вызова lockf, fcntl ).
- Этот столбец предназначен для типа блокировки. Он может иметь два значения: КОНСУЛЬТАТИВНЫЙ или ОБЯЗАТЕЛЬНЫЙ .
- Четвертое поле показывает, является ли блокировка WRITE или READ lock.
- Затем у нас есть идентификатор процесса, удерживающего блокировку.
- Это поле содержит строку значений, разделенных двоеточиями, показывающую идентификатор заблокированного файла в формате « major-device: minor-device: inode ».
- Этот столбец, вместе с последним, показывает начало и конец заблокированной области блокируемого файла. В этом примере строки заблокирован весь файл.
5. Введение в команду flock
Команда flock также предоставляется командой util-linux package. Эта утилита позволяет нам управлять блокировками рекомендательных файлов в сценариях оболочки или в командной строке..
Основной синтаксис использования:
flock FILE_TO_LOCK COMMAND
Далее давайте продемонстрируем наш пример обновления баланса с помощью команды flock .
В дополнение к текстовому файлу balance.dat , содержащему текущее значение баланса, нам все еще нужны два процесса, A и B, для обновления баланса в файле.
Сначала мы создаем простой сценарий оболочки update_balance.sh для обработки логики обновления баланса для обоих процессов:
#!/bin/bashfile = "balance.dat" value = $ (cat $ file) echo "Прочитать текущий баланс: $ value "# спать 10 секунд для имитации бизнес-расчетовprogress = 10 while [[$ progress -lt 101]]; do echo -n -e " 033 [77DCalculating new balance .. $ progress%" sleep 1 progress = $ ((10 + progress)) doneecho "" value = $ ((value + $ 1)) echo "Записать новый баланс ($ value) обратно в $ file. " echo $ value> "$ file" echo "Done."
Мы создаем простой сценарий оболочки a.sh для моделирования процесса A:
#!/bin/bash # ------------------------------ ----------- # процесс A: заблокировать файл и вычесть 20 # из текущего баланса # ----------------------- ------------------ flock --verbose balance.dat ./update_balance.sh '-20'
Теперь приступим процесс A для проверки:
$ ./a.sh flock: получение блокировки заняло 0,000002 секундыflock: выполнение ./update_balance.sh Чтение текущего баланса: 100 Расчет нового баланса..100% Запись новый баланс (80) обратно в balance.dat.Done.
В выводе мы видим, что команда flock сначала установила блокировку файл balance.dat , затем скрипт update_balance.sh прочитал и обновил файл.
Во время его запуска мы можно проверить информацию о блокировке с помощью команды lslocks :
$ lslocks | grep 'balance'flock 825712 FLOCK 4B WRITE 0 0 0/tmp/test/balance.dat
Вывод показывает, что команда flock удерживание блокировки WRITE для всего файла /tmp/test/balance.dat .
5.1. Демонстрация flock с некооперативными процессами
Мы узнали, что рекомендательные блокировки работают, только если участвующие процессы взаимодействуют . Давайте сбросим баланс до 100 и проверим, что произойдет, если мы установим консультативную блокировку файла для процесса A, но запустим процесс B без взаимодействия.
Теперь давайте создадим простую оболочку скрипт b_non-cooperative.sh :
#!/bin/bash # ------------- --------------------------- # процесс B: добавить 80 к текущему балансу # без взаимодействия # ------ ----------------------------------./update_balance.sh '80'
Мы видим, что процесс B вызывает update_balance.sh , не пытаясь получить блокировку файла данных баланса.
Давайте продемонстрируем этот сценарий на GIF-анимация:
Мы видим, что консультативная блокировка, полученная процессом A, игнорируется, если процесс B запускается без взаимодействия с процессом A.
Следовательно, у нас 180 вместо 160 в the balance.dat .
5.2. Демонстрация flock с кооперативными процессами
Наконец, давайте создадим еще один кооперативный процесс B, b.sh , и посмотрим, как работает консультативная блокировка:
#!/bin/bash # ---------------------------------------- # процесс B: добавить 80 к текущему балансу # кооперативным способом # ----------------------------------- ----- flock --verbose balance.dat ./update_balance.sh '80'
Мы снова показываем демонстрацию в формате GIF:
В демонстрации мы сделали два процесса для взаимодействия.
Мы заметили, что когда процесс B пытался получить блокировку для файла balance.dat , он ждал, пока процесс A снимет блокировку . Таким образом, консультативная блокировка g, и мы получили ожидаемый результат 160 в файле данных баланса.
6. Заключение
В этой статье мы начали с понимания проблемы промежуточного обновления. Затем мы обсудили различные типы схем блокировки файлов в системах Linux.
Мы также изучили команду lslocks для проверки блокировок в системе и команду flock для реализации рекомендательной блокировки.
Наконец, мы увидели две демонстрации. Один помог нам понять взаимосвязь между консультативной блокировкой и взаимодействием процессов, а другой показал нам, как работает консультативная блокировка.