Операционная система UNIX - страница 115
1. Значение семафора должно быть доступно различным процессам. Поэтому семафор находится не в адресном пространстве процесса, а в адресном пространстве ядра.
2. Операция проверки и изменения значения семафора должна быть реализована в виде одной атомарной по отношению к другим процессам (т. е. непрерываемой другими процессами) операции. В противном случае возможна ситуация, когда после проверки значения семафора выполнение процесса будет прервано другим процессом, который в свою очередь проверит семафор и изменит его значение. Единственным способом гарантировать атомарность критических участков операций является выполнение этих операций в режиме ядра (см. режимы выполнения процесса).
Таким образом семафоры являются системным ресурсом, действия над которым производятся через интерфейс системных вызовов.
Семафоры в System V обладают следующими характеристиками:
□ Семафор представляет собой не один счетчик, а группу, состоящую из нескольких счетчиков, объединенных общими признаками (например, дескриптором объекта, правами доступа и т.д.).
□ Каждое из этих чисел может принимать любое неотрицательное значение в пределах, определенных системой (а не только значения 0 и 1).
Для каждой группы семафоров (в дальнейшем мы будем называть группу просто семафором) ядро поддерживает структуру данных >semid_ds
, включающую следующие поля:
>struct ipc_perm sem_perm | Описание прав доступа |
>struct sem *sem_base | Указатель на первый элемент массива семафоров |
>ushort sem_nsems | Число семафоров в группе |
>time_t sem_otime | Время последней операции |
>time_t sem_ctime | Время последнего изменения |
Значение конкретного семафора из набора хранится во внутренней структуре >sem
:
>ushort semval | Значение семафора |
>pid_t sempid | Идентификатор процесса, выполнившего последнюю операцию над семафором |
>ushort semncnt | Число процессов, ожидающих увеличения значения семафора |
>ushort semzcnt | Число процессов, ожидающих обнуления семафора |
Помимо собственно значения семафора, в структуре sem хранится идентификатор процесса, вызвавшего последнюю операцию над семафором, число процессов, ожидающих увеличения значения семафора, и число процессов, ожидающих, когда значение семафора станет равным нулю. Эта информация позволяет ядру производить операции над семафорами, которые мы обсудим несколько позже.
Для получения доступа к семафору (и для его создания, если он не существует) используется системный вызов semop(2):
>#include
>#include
>#include
>int semget(key_t key, int nsems, int semflag);
В случае успешного завершения операции функция возвращает дескриптор объекта, в случае неудачи - -1. Аргумент >nsems
задает число семафоров в группе. В случае, когда мы не создаем, а лишь получаем доступ к существующему семафору, этот аргумент игнорируется. Аргумент >semflag
определяет права доступа к семафору и флажки для его создания (>IPC_CREAT
, >IPC_EXCL
).
После получения дескриптора объекта процесс может производить операции над семафором, подобно тому, как после получения файлового дескриптора процесс может читать и записывать данные в файл. Для этого используется системный вызов semop(2):
>#include
>#include
>#include
>int semop(int semid, struct sembuf *semop, size_t nops);
В качестве второго аргумента функции передается указатель на структуру данных, определяющую операции, которые требуется произвести над семафором с дескриптором >semid
. Операций может быть несколько, и их число указывается в последнем аргументе >nops
. Важно, что ядро обеспечивает атомарность выполнения критических участков операций (например, проверка значения — изменение значения) по отношению к другим процессам.
Каждый элемент набора операций >semop
имеет вид:
>struct sembuf {
> short sem_num; /* номер семафора в группе */
> short sem_op; /* операция */
> short sem_flg; /* флаги операции */
>}
UNIX допускает три возможные операции над семафором, определяемые полем >semop
:
1. Если величина >semop
положительна, то текущее значение семафора увеличивается на эту величину.
2. Если значение >semop
равно нулю, процесс ожидает, пока семафор не обнулится.