Способы использования семафоров
Семафоры могут применяться для различных целей. Их можно использовать для взаимного исключения, синхронизации взаимодействия процессов и управления выделением ресурсов. В зависимости от конкретного применения используются разные начальные значения семафора и различные последовательности вызова методов SImWait() и SimSignal().
1) Взаимоисключения – с помощью семафора, инициализированного значением 1 можно обеспечить монопольный доступ к общему ресурсу (например, к совместно используемой структуре данных).
В описанном применении первым в критическую секцию входит процесс, который первым запросил ее использование с помощью вызова SimWait(). Способ планирования процессов зависит от конкретной реализации и не является частью концепции семафора. Например, при выполнении одним из процессов вызова SimSignal() можно освободить все ожидающие процессы и тогда в критическую секцию войдет тот из них, который первым снова выполнит вызов SimWait(). В этом случае выбор процесса будет определятся алгоритмом планирования, используемым в ОС. Еще одна альтернатива заключается в организации планирования для очередей семафора на основе приоритета процессов, которые в этом случае должны быть известны семафору.
2) Условная синхронизация – два взаимосвязанных процесса должны иметь возможность синхронизировать свои действия. Процессы могут быть связаны следующим образом: при достижении процессом А определенной точки, он не может продолжить роботу, пока процесс В не выполнит некоторую задачу. Для их синхронизации можно применять инициализированный значением 0 семафор, у которого процесс А должен ждать в точке синхронизации, выполнив вызов SimWait(), пока процесс В не вызовет метод SimSignal(). Особенность данного способа применения семафора заключается в том, что вызов SimWait() выполняет один процесс, а вызов SimSignal() – другой.
Семафор используемый таким образом называется приватным, ждать у него может только один процесс, сигнализировать с его помощью о программных событиях может произвольное количество процессов.
3) Использование более одного экземпляра ресурса. В ОС типичной бывает ситуация, когда несколько процессов имеют возможность обращаться к ресурсу одновременно, но количество таких обращений должно быть ограничено. Если в системе имеется два принтера, которые представляют собой ресурс, которым одновременно могут пользоваться несколько процессов, соответствующий семафор этого ресурса нужно инициализировать значением 2. Каждый раз, когда некоторый процесс запрашивает доступ к ресурсу и значение семафора этого ресурса больше 0, данное значение уменьшается на 1. Как только значение семафора станет равным 0, последующие попытки доступа к ресурсу должны быть блокированы, а соответствующие процессы установлены в очередь. После ого, как процесс освободит ресурс, семафор проверит имеющиеся в очереди другие процессы. При их отсутствии значение семафора увеличивается на 1, в противном случае одному из процессов предоставляется доступ к ресурсу.
Для того, чтобы семафор можно было использовать описанным способом, его метод SimWait() должен устанавливать процесс в очередь. Освобождая ресурс, процесс должен вызвать метод SimSIgnal(), при этом каждый ресурс следует защитить собственным семафором.
Для успешного функционирования семафора недостаточно одних атомарных операций SimWait() и SimSignal(). Необходимо также, чтобы эти операции начавших обязательно завершились, причем без чрезмерных задержек. Проверка и изменение значения семафора задержек не вызывает. Изменение состояния процесса требует доступа к его дескриптору, возможно с вызовом операций блокировать и разблокировать, реализованных в другом модуле.
Доступ к дескриптору процесса может осуществляться от имени другого процесса. Если предположить, что время выполнения операций блокировать и разблокировать фиксировано, то можно гарантировать и время выполнения операций SimWait() и SimSiganl().
При разработке системы, в которой присутствуют семафоры, необходимо доказать, что вызовы между классами семафоров и процессов не приведут к взаимоблокировке, т.е.при построении ОС необходимо разработать атомарные, правильно функционирующие операции SimWait() и SimSiganl() с фиксированным временем выполнения.