Введение в блокировку файлов в Linux

1. Обзор

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

В этом руководстве мы поймем проблему промежуточного обновления в системе с несколькими процессами. Затем мы собираемся представить два типа блокировок в Linux.

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

2. Проблема промежуточного обновления

Промежуточное обновление – это типичная проблема состояния гонки в параллельной системе . Давайте посмотрим на пример, чтобы лучше понять проблему.

Допустим, у нас есть файл balance.dat , в котором хранится баланс учетной записи, и он имеет начальное значение из « 100 «. В нашей параллельной системе есть два процесса для обновления значения баланса:

  1. Процесс A: считывает текущее значение, вычитает 20 и сохраняет результат обратно в файл.
  2. Процесс B: считывает текущее значение, добавляет 80 и записывает результат обратно в файл.

Очевидно, что после выполнения двух процессов мы ожидаем файл имеет значение: 100-20+80=160.

Однако в этой ситуации может возникнуть промежуточная проблема обновления:

  1. Процесс A считывает текущее значение файла ( 100 ) и готовится к дальнейшим вычислениям.
  2. Процесс B теперь читает тот же файл и получает текущий баланс ( 100 ).
  3. Процесс A вычисляет 100-20 и сохраняет результат 80 обратно к файлу.
  4. Процесс B не знает, что баланс был обновлен с момента последнего чтения. Таким образом, он по-прежнему будет использовать устаревшее значение 100 для вычисления 100 + 80 и записи результата 180 в файл. .

В результате мы имеем 180 в файле balance.dat вместо ожидаемого значения 160.

3. Блокировка файлов в Linux

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

Все мы знаем, что rm – rf/ – очень опасная команда в Linux. Если мы выполним команду как пользователь root , все файлы в работающей системе будут удалены. Это связано с тем, что Linux обычно не блокирует открытые файлы автоматически. Однако Linux поддерживает два вида блокировок файлов: рекомендательные блокировки и обязательные блокировки.

Вскоре мы представим оба типа блокировки, но в этой статье основное внимание будет уделено рекомендательной блокировке. р>

3.1. Консультативная блокировка

Консультативная блокировка не является принудительной схемой блокировки. Это будет работать, только если участвующие процессы взаимодействуют, явно устанавливая блокировки. В противном случае рекомендательные блокировки будут игнорироваться, если процесс вообще не знает о блокировках..

Пример может помочь нам легче понять схему совместной блокировки. Давайте рассмотрим наш предыдущий пример баланса.

  1. Во-первых, мы предполагаем, что файл balance.dat все еще содержит начальное значение « 100 “.
  2. Процесс A устанавливает исключительную блокировку файла balance.dat , затем открывает и читает файл, чтобы получить текущую value: 100.

Мы должны понимать, что консультативная блокировка не была установлена ​​операционной системой или файловой системой. Следовательно, даже если процесс A блокирует файл, процесс B по-прежнему может читать, записывать или даже удалять файл с помощью системных вызовов.

Если процесс B выполняет файловые операции, не пытаясь получить блокировку, мы говорим, что процесс B не взаимодействует с процессом A.

Но теперь давайте взглянем на как блокировка будет работать для взаимодействующих процессов :

  1. Процесс B пытается получить блокировку на balance.dat перед чтением файла (взаимодействуя с процессом A).
  2. Поскольку процесс A заблокировал файл, процесс B должен ждать, пока процесс A снимет блокировку.
  3. Процесс A вычисляет 100-20 и записывает 80 обратно в файл.
  4. Процесс A снимает блокировку.
  5. Теперь процесс B получает блокировку и читает файл, получая обновленное значение: 80.
  6. Процесс B запускает свою логику и записывает результат 160 ( 80 + 80 ) обратно в файл.
  7. Процесс B снимает блокировку, чтобы другие взаимодействующие процессы могли читать и писать в файл.

Мы увидим, как этот пример реализуется с помощью flock в следующем разделе.

3.2. Обязательная блокировка

Прежде чем мы начнем рассматривать обязательную блокировку файлов, мы должны помнить, что « реализация принудительной блокировки в Linux ненадежна «.

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

Чтобы включить принудительную блокировку файлов в Linux, необходимо выполнить два требования:

  1. Мы должны смонтировать файловую систему с параметром mand ( mount – o mand FILESYSTEM MOUNT_POINT ).
  2. Мы должны включить бит 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-  
  1. Первый столбец – это порядковый номер.
  2. Второе поле указывает класс используемой блокировки, например FLOCK ( из системного вызова flock ) или POSIX (из системного вызова lockf, fcntl ).
  3. Этот столбец предназначен для типа блокировки. Он может иметь два значения: КОНСУЛЬТАТИВНЫЙ или ОБЯЗАТЕЛЬНЫЙ .
  4. Четвертое поле показывает, является ли блокировка WRITE или READ lock.
  5. Затем у нас есть идентификатор процесса, удерживающего блокировку.
  6. Это поле содержит строку значений, разделенных двоеточиями, показывающую идентификатор заблокированного файла в формате « major-device: minor-device: inode ».
  7. Этот столбец, вместе с последним, показывает начало и конец заблокированной области блокируемого файла. В этом примере строки заблокирован весь файл.

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 для реализации рекомендательной блокировки.

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

Оцените статью
futurei.ru
Добавить комментарий