А. Робачевский - Операционная система UNIX (1114671), страница 50
Текст из файла (страница 50)
Тогда перед началом работы с ре!сурсом процесс должен проверить значение счетчика. Если оно равно 0 —ресурс занят и операция недопустима — процессу остается ждать. Еслизначение счетчика равно 1 — можно работать с ресурсом. Для этого, пре!жде всего, необходимо заблокировать ресурс, т. е. изменить значение счет!чика на 0. После выполнения операции для освобождения ресурса значе!ние счетчика необходимо изменить на 1. В приведенном примере счетчикиграет роль семафора.Для нормальной работы необходимо обеспечить выполнение следующихусловий:www.books-shop.com254Глава 3.управления процессами1.
Значение семафора должно быть доступно различным процессам. По!этому семафор находится не в адресном пространстве процесса, а вадресном пространстве ядра.2. Операция проверки и изменения значения семафора должна быть реа!лизована в виде одной атомарной по отношению к другим процессам(т. е. непрерываемой другими процессами) операции. В противномслучае возможна ситуация, когда после проверки значения семафоравыполнение процесса будет прервано другим процессом, который всвою очередь проверит семафор и изменит его значение. Единствен!ным способом гарантировать атомарность критических участков опе!раций является выполнение этих операций в режиме ядра (см.
режи!мы выполнения процесса).Таким образом семафоры являются системным ресурсом, действия надкоторым производятся через интерфейс системных вызовов.Семафоры в System V обладают следующими характеристиками:Семафор представляет собой не один счетчик, а группу, состоящуюиз нескольких счетчиков, объединенных общими признаками (на!пример, дескриптором объекта, правами доступа и т. д.).Каждое из этих чисел может принимать любое неотрицательное значе!ние в пределах, определенных системой (а не только значения 0 и 1).Для каждой группы семафоров (в дальнейшем мы будем называть группупросто семафором) ядро поддерживает структуру данныхвклю!чающую следующие поля:structstructsem_nsemsОписание прав доступаУказатель на первый элемент массива семафоровЧисло семафоров в группеВремя последней операцииВремя последнего измененияЗначение конкретного семафора из набора хранится во внутренней струк!туре sem:ushortushortushortsemvalsempidЗначение семафораИдентификатор процесса, выполнившего послед!нюю операцию над семафоромЧисло процессов, ожидающих увеличения значе!ния семафораЧисло процессов, ожидающих обнуления сема!фораПомимо собственно значения семафора, в структуре sem хранится иден!тификатор процесса, вызвавшего последнюю операцию над семафором,число процессов, ожидающих увеличения значения семафора, и числоwww.books-shop.comВзаимодействиепроцессами255процессов, ожидающих, когда значение семафора станет равным нулю.Эта информация позволяет ядру производить операции над семафорами,которые мы обсудим несколько позже.Для получения доступа к семафору (и для его создания, если он не суще!ствует) используется системный вызовttinclude#include <sys/ipc.h>ttinclude <sys/sem.h>intkey, intintВ случае успешного завершения операции функция возвращает дескрип!тор объекта, в случае1.
Аргументзадает число семафо!ров в группе. В случае, когда мы не создаем, а лишь получаем доступ ксуществующему семафору, этот аргумент игнорируется. Аргумент s e m f l a gопределяет права доступа к семафору и флажки для его создания(IPC_CREAT, IPC_EXCL).После получения дескриптора объекта процесс может производить опера!ции над семафором, подобно тому, как после получения файлового деск!риптора процесс может читать и записывать данные в файл. Для этого ис!пользуется системный вызовttincludettincludettincludeint s e m o p ( i n tstructsize_tВ качестве второго аргумента функции передается указатель на структуруданных, определяющую операции, которые требуется произвести над се!мафором с дескриптором semid.
Операций может быть несколько, и ихчисло указывается в последнем аргументе nops. Важно, что ядро обеспе!чивает атомарность выполнения критических участков операций(например, проверка значения — изменение значения) по отношению кдругим процессам.Каждый элемент набора операцийstruct sembuf {short semshortshort semимеет вид:/*номер семафора вUNIX допускает три возможные операции над семафором, определяемыеполем semop:1.
Если величина semop положительна, то текущее значение семафораувеличивается на эту величину.www.books-shop.com256Глава 3.управления процессами2. Если значение semop равно нулю, процесс ожидает, пока семафор необнулится.Если величина semop отрицательна, процесс ожидает, пока значениесемафора не станет большим или равным абсолютной величинеsemop. Затем абсолютная величина semop вычитается из значения се!мафора.Можно заметить, что первая операция изменяет значение семафора(безусловное выполнение), вторая операция только проверяет его значениевыполнение), а третья — проверяет, а затем изменяет значениесемафора (условное выполнение).При работе с семафорами взаимодействующие процессы должны догово!риться об их использовании и кооперативно проводить операции над се!мафорами.
Операционная система не накладывает ограничений на исполь!зование семафоров. В частности, процессы вольны решать, какое значениесемафора является разрешающим, на какую величину изменяется значениесемафора и т. п.Таким образом, при работе с семафорами процессы используют различныекомбинации из трех операций, определенных системой, по!своему трактуязначения семафоров.В качестве примера рассмотрим два случая использования бинарного сема!фора (т.
е. значения которого могут принимать только 0 и 1). В первомпримере значение 0 является разрешающим, а 1 запирает некоторый разде!ляемый ресурс (файл, разделяемая память и т. п.), ассоциированный с се!мафором. Определим операции, запирающие ресурс и освобождающие его:static structО, О, О,О, 1, 0= {обнуления/*затем увеличить значение семафора наstatic struct sembuf sop unlock [1] = {0,0значениеИтак, для запирания ресурса процессвызов:обеспечивающий атомарное выполнение двухЯдро обеспечивает атомарное выполнение не всего набора операций в целом, а лишь кри!тических участков.
Так, например, в процессе ожидания освобождения ресурса (ожиданиенулевого значения семафора) выполнение процесса будет (и должно быть) прервано про!цессом, который освободит ресурс (т. е. установит значение семафора равным 1). Ожида!ние семафора соответствует"сна" процесса, допускающим выполнение другихпроцессов в системе. В противном случае, процесс, ожидающий ресурс, остался бы забло!кированным навсегда.www.books-shop.comпроцессами2571.
Ожидание доступности ресурса. В случае, если ресурс уже занят(значение семафора равно 1), выполнение процесса будет приостанов!лено до освобождения ресурса (значение семафора равно 0).2. Запирание ресурса. Значение семафора устанавливается равнымДля освобождения ресурса процесс должен произвести вызов:который уменьшит текущее значение семафора (равное 1) наи оно ста!нет равным 0, что соответствует освобождению ресурса.
Если какой!либоиз процессов ожидает ресурса (т. е. произвел вызов операции sop_lock),он будет "разбужен" системой, и сможет в свою очередь запереть ресурс иработать с ним.Во втором примере изменим трактовку значений семафора: значению 1семафора соответствует доступность некоторого ассоциированного с сема!фором ресурса, а нулевому значению —недоступность. В этом случаесодержание операций несколько изменится.static structО, 1, 0,= {разрешающего сигнала (1),затем обнулитьstatic struct sembuf sop_unlock [1] = {О, 1, 0значение семафора наПроцесс запирает ресурс вызовом:1);а освобождает:Во втором случае операции получились проще (по крайней мере их кодстал компактнее), однако этот подход имеет потенциальную опасность:при создании семафора, его значения устанавливаются равными 0, и вовтором случае он сразу же запирает ресурс.
Для преодоления данной си!туации процесс, первым создавший семафор, должен вызвать операциюоднако в этом случае процесс инициализации семафора пе!рестанет быть атомарным и может быть прерван другим процессом, кото!рый, в свою очередь, изменит значение семафора. В итоге, значение сема!фора станет равным 2, что повредит нормальной работе с разделяемымресурсом.Можно предложить следующее решение данной проблемы:семафор, если он уже существуетвозвращаетошибку, поскольку указан флагif ( (semid = semget. ( key,< 0)permsIPC_CREAT I)www.books-shop.com258Глава 3.if/правления процессами(errno = EEXIST){if (ошибка вызвана существованием=key,perms ) ) < 0)не хватает системных}elseне хватает системныхсемафор создан нами,elseРазделяемая памятьИнтенсивный обмен данными между процессами с использованием рас!смотренных механизмов межпроцессного взаимодействия (каналы, FIFO,очереди сообщений) может вызвать падение производительности системы.Это, в первую очередь, связано с тем, что данные, передаваемые с помо!щью этих объектов, копируются из буфера передающего процесса в буферядра и затем в буфер принимающего процесса.
Механизм разделяемой па!мяти позволяет избавиться от накладных расходов передачи данных черезядро, предоставляя двум или более процессам возможность непосредст!венного получения доступа к одной области памяти для обмена данными.Безусловно, процессы должны предварительно "договориться" о правилахиспользования разделяемой памяти. Например, пока один из процессовпроизводит запись данных в разделяемую память, другие процессы долж!ны воздержаться от работы с ней. К счастью, задача кооперативного ис!пользования разделяемой памяти, заключающаяся в синхронизации вы!полнения процессов, легко решается с помощью семафоров.Примерный сценарий работы с разделяемой памятью выглядит следую!щим образом:1.