Поток управления может быть заблокирован в ожидании сигналов с внешних устройств или специальных объектов ОС, в ожидании освобождения используемых в данный момент файлов или других видов ресурсов. Таким образом выполняется синхронизация работы параллельно выполняющихся задач, а также обеспечивается корректность доступа к таким видам ресурсов, которые не допускают своего одновременного использования различными задачами.
Доступ к файлам полностью контролируется операционной системой. Файлы имеют различные режимы доступа, причем в некоторых из этих режимов одновременный доступ к файлу запрещен. Например (в общем случае), если файл открыт одним процессом для записи, то попытка второго процесса открыть его для записи приводит к ошибке. Существуют также режимы создания файла, при которых создание завершается успешно, только если файл отсутствует в целевой файловой системе, с генерацией ошибки в противном случае. Данный факт можно использовать для эмуляции объекта синхронизации мьютех (взаимное исключение, mutex). Мьютексом называется объект синхронизации, для которого определены в общем случае две операции: захватить и освободить. Захват мьютекса блокирует его для других потоков управления, освобождение - разблокирует. Таким образом, если один поток управления успешно захватил мьютекс, остальные потоки при попытке захвата будут заблокированы до тех пор, пока исходный поток не освободит мьютекс, после чего один из заблокированных на мьютексе потоков немедленно его захватывает.
Файл, с помощью которого будет эмулироваться мьютекс назовем файлом блокировки. Блокировка в указанном случае не будет полной, т.к. в действительности задача, пытающаяся создать или получить доступ к заблокированному файлу, не приостановливается, а продолжает свое выполнение, сгенерировав ошибку ввода-вывода. Обеспечить эмуляцию блокировки можно, организовав цикл, в котором производятся попытки создать или открыть файл блокировки до тех пор, пока данное действие не закончится удачно. Такой подход является не эффективным с точки зрения расхода ресурсов микропроцессора, однако исторически именно он использовался впервые для синхронизации доступа к ресурсам. Некоторое снижение нагрузки на процессор может быть обеспечено блокировкой задачи на определенный промежуток времени между попытками захвата мьютекса.
При использовании Windows для выбора механизма блокировок разработать программу, которая определяет,
какие типы файлов и в каких режимах открытия файла
блокирует операционная система при повторной попытке открытия, либо какой способ
создания файла блокирует другие процессы при попытке повторного создания. На основе результатов
исследования разработать процедуры (вариант для FreePascal):
procedure GetMutex(filename:string); - процедура, обеспечивающая эксклюзивный
захват файла блокировок. Выход из процедуры - при удачном захвате. Если захват
неудачен, процедура повторяет попытки захвата до успеха.
procedure ReleaseMutex(filename:string); - процедура, освобождающаяя
захваченный ранее файл блокировок.
При использовании Linux
для создания процедур GetMutex
и ReleaseMutex можно воспользоваться (вариант для FreePascal)
функциями fpOpen, fpClose, fpUnlink из модуля baseunix:
Вызов fpOpen('имя файла',O_Creat or O_Excl, S_IRWXU) создает файл и возвращает его числовой файловый дескриптор.
Если такой файл уже существует, то будет возвращено значение -1. Если файл не существует, он будет создан
и эксклюзивно захвачен создавшим его процессом. Для остальных процессов файл будет заблокирован.
Вызов fpClose(файловый_дескриптор) закрывает файл.
Вызов fpUnlink('имя файла') удаляет файл.
Более подробно о режимах открытия и механизмах блокировок файлов можно узнать с помощью команды man 2 open
Дополнительные задания:
Тестовые решения:
Реализация getMutex, releaseMutex и тестовая программа для ОС Linux
Бинарное решение (без дополнительных заданий) для ОС Linux