Блокировка файла. Множественный доступ к файлу

Автор: Тарасов А.Е. (ТАЕ)

Рецензент: Кузнецов В.А.

Дата: 01.2015

Скачать статью в формате Word

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

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

  • Атрибуты файла.
  • Семафоры, типа «взаимное исключение» (mutex).
  • Использование файла флага.

Давайте отдельно остановимся на каждом из них:

 

* Атрибуты файла.

 

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

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

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

В RexxUtil есть команда SysFileTree - получение информации о файлах (списках файлов). С её помощью можно не только искать файлы по маске атрибутов, но и устанавливать нужные атрибуты у всех найденных файлов.

Ложка дегтя оказалось в том, что в интерпретаторе Regina (который я использую в Windows) не реализована возможность установки атрибутов файлов. О чем прямо написано в документации. Иной возможности установить атрибуты файлов средствами Rexx найти не удалось. Что заставило воспользоваться для этих целей внешней утилитой, которая есть в любой ОС «attrib». Это решение значительно повысило временные расходы. Но лучше пока, ни чего нет.

В приведенных примерах в переменной «FileActual» содержится путь и имя файла, который необходимо блокировать.

 

         /* Защита от одновременной записи в файл через атрибуты (одиночная блокировка) */

         do until FileActual.0>0
            call SysFileTree FileActual, 'FileActual','FN','**-*-'
            if FileActual.0>0 then 'attrib +h "'FileActual'" > nul'
            else call SysSleep Random(1,5)/10
         end /* until FileSearch.0>0 */
 

         /* Снятие защиты файла */

         'attrib -h -s "'FileActual'" > nul'

 

         /* Защита от одновременной записи в файл через атрибуты (двойная блокировка) */

         do until FileActual.0>0

            call SysFileTree FileActual, 'FileActual','FN','**-*-'

            if FileActual.0>0 then do

               'attrib +h "'FileActual'" > nul'

               call SysSleep Random(2,10)/100 /* Пауза для раз синхронизации процессов 0,02-0,1 сек.*/

               call SysFileTree FileActual, 'FileActual','FN','**+*-'

               if FileActual.0>0 then 'attrib +s "'FileActual'" > nul'

            end /* if */

            else call SysSleep Random(1,5)/10 /* Пауза ожидания освобождения файла 0,1-0,5 сек.*/

         end /* until FileSearch.0>0  */

 

         /* Снятие защиты файла */

         'attrib -h -s "'FileActual'" > nul'

 

* Семафоры, типа «взаимное исключение» (mutex).

 

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

Как правило, семафоры используются для управления множественного доступа к ресурсу и совместного использование одного ресурса несколькими процессами. Семафоры определяется системой, и размещаются во внутренней памяти. Имена семафора должно включать префикс '/SEM32/'. Максимальная длина имени семафора в разных источниках указана разная. В инструкции к RexxUtil для OS/2 указана максимальная длина имени 255 символов, тогда как в «IBM Knowledge Center» (https://www-01.ibm.com/support/knowledgecenter/SSZND2_6.0.0/com.ibm.etools.iseries.orxw.doc/orxw_ref603.htm?lang=ru) для Object REXX указана максимальная длина 63 символа.

Rexx позволяет работать с двумя видами семафоров:

  • «взаимное исключение» (mutex) - используется для систематизации доступа к ресурсам.
  • «множественное ожидание» (muxwait) — ожидание наступления нескольких событий для доступа к ресурсам. Управление ожиданием наступления события происходит через «события семафора» (Event semaphores).

Семафоры управляются командами RexxUtil: SysCreate...() SysOpen...(), и SysClose...(). Дополнительно семафоры «взаимного исключения» (Mutex) управляются командами SysReleaseMutexSem() и SysRequestMutexSem(), а «события семафоров» управляются через команды: SysPostEventSem(), SysResetEventSem(), и SysWaitEventSem().

Для решения задачи множественного доступа к файлу воспользуемся семафором «взаимного исключения» (mutex).

В примерах переменная «SemName» содержит имя семафора.

 

         /* Защита от одновременной записи в файл через семафоры*/

         SemName='/SEM32/'Year||MonthDay

         SemName=SysCreateMutexSem(SemName)

         do while SysRequestMutexSem(SemName,10)<>0

         end /* until */

 

         /* Снятие защиты файла */

         call SysReleaseMutexSem SemName

         call SysCloseMutexSem SemName

 

* Использование файла флага.

 

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

При проработки этой темы рассматривалось два сценария работы:

  1. Создание файла блокировки при начале работе с исходным файлом, и последующее удаление флага. Ищем наличие флага.
  2. Изначальное создание файлов флагов для каждого файла, а при начале работы с исходным файлом перемещение (move) файла флага во временный каталог, с последующим возвратом. Ищем отсутствие файла.

Второй вариант, хоть и приводит к удвоению файлов, но должен позволять обойти ряд скольких мест. Не смотря на это, было принято решение все-таки реализовывать только первый вариант.

В приведенных примерах в переменной «FileActual» содержится путь и имя файла, который необходимо блокировать.

 

         /* Защита от одновременной записи в файл через lock файл*/

         do until FileActual.0=0

            call SysFileTree FileActual'.lock', 'FileActual','FN','*****'

            if FileActual.0=0 then call lineout FileActual'.lock'

            else call SysSleep Random(1,5)/10

         end /* until FileSearch.0=0 */

 

         /* Снятие защиты файла */

         call sysFileDelete FileActual'.lock'

 

Сравнительный анализ.

 

Теперь давайте сравним приведенные методы блокировки файлов между собой. Для чего проведем ряд тестовых запусков одного итого же скрипта, но с разными системами блокировка. Обрабатывать будем 209 файлов, общим объемом 6.7Мб.

Необходимо выбрать скрипт который агрессивно пытается забирать файла на монопольное использование. Для этих целей идеально подходит скрипт аналог команды “update”. Перед нашим скриптом поставим задачу проверить каждую строку в каждом файле на соответствие неким условиям, и если условия выполняются внести изменения в строку, после чего переписать файл. Условия подобраны так, что в каждом файле, будут найдены одна или несколько строк, для внесения изменений.

Для получения статистически данных, каждый вариант блокировки будет протестирован трижды.

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

 

Метод блокировки

Атрибуты

Семафоры

Файлы

1

68,985

31,196

23,335

2

57,135

23,258

22,997

3

58,355

22,495

23,031

Минимальные значения

57,135

22,495

22,997

Средние значения

61,492

25,650

23,121

 

 

Как видно из таблицы, минимальное время зафиксировано при использовании алгоритма на основе семафоров. За ним с минимальной разницей в 0,502 сек. идет метод на основе файловых флагов. А метод на основе использования атрибутов значительно проигрывает, что связано с вынужденным использованием внешней командой системы «attrib». Считаю, что если удастся найти замену команде «attrib», то результат будет как минимум на том же уровне.

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

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

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

Данные по тестовым запускам сведем в следующую таблицу.

 

Атрибуты

Значения

 

1

2

3

4

Минимальные

1

72,867

81,024

79,432

66,356

66,356

74,920

2

79,848

80,852

81,323

81,323

79,848

80,837

3

72,999

71,396

73,203

71,390

71,390

72,247

Итого:

66,356

76,001

Семафоры

Значения

1

2

3

4

Минимальные

Средние

1

37,689

38,055

36,859

35,822

35,822

37,106

2

38,211

38,957

39,270

37,918

37,918

38,589

3

37,965

38,814

37,962

36,691

36,691

37,858

Итого:

35,822

37,851

Файлы

Значения

1

2

3

4

Минимальные

Средние

1

31,878

36,641

35,33

35,972

31,878

34,955

2

34,446

34,608

35,179

35,694

34,446

34,982

3

26,121

33,723

32,165

32,286

26,121

31,074

Итого:

26,121

33,670

 

 

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

 

Выводы.

 

В данной статье мы рассмотрели три способы решения в Rexx задачи блокировки файлов при множественном доступе к нему. Эти методы, основанные на использовании:

  • Атрибуты файла,
  • Семафоры, типа «взаимное исключение» (mutex).
  • Использование файла флага.

 

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

Окончательное решение, какой же метод использовать должен принимать программист, исходя из поставленной задачи и внешними факторами.