![]() |
![]() |
Главная страница Взаимодействие нетривиальных процессов каждым Sem wa1t, чтобы было ясно, какой из потоков ожидает изменения семафора. Добавьте еще один вызов printf после каждого Sem wait, чтобы можно было определить, какой поток получил управление. Уменьшите количество буферов до двух, а затем откомпилируйте и выполните эту программу, чтобы убедиться, что она зависнет. 2. Предположим, что запущено четыре экземпляра программы, вызывающей функцию ту 1оск из листинга 10.10: % lockpxsem & lockpxsem & lockpxsem & lockpxsem & Каждый из четырех процессов запускается с значением initflag, равным О, поэтому при вызове sem open всегда указывается 0 CREAT. Нормально ли это? 3. Что произойдет в предыдущем примере, если одна из четырех программ будет завершена после вызова ту 1 оск, но перед вызовом my unl оск? 4. Что произошло бы с программой в листинге 10.22, если бы мы не инициализировали оба дескриптора значением -1? 5. Почему в листинге 10.22 мы сохраняем значение errno, а затем восстанавливаем его, вместо того чтобы написать просто: if (sem->fd[0] >- 0) close(sem->fd[0]): if (sem->fd[l] >= 0) close(sem->fd[l]): 6. Что произойдет, если два процесса вызовут нашу реализацию sem open через FIFO (листинг 10.22) примерно одновременно, указывая флаг 0 CREAT и начальное значение 5? Может ли канал быть инициализирован (неправильно) значением 10? 7. В связи с листингами 10.28 и 10.29 мы описали возможную ситуацию гонок в случае, если два процесса пытаются создать семафор примерно одновременно. Однако решение предыдущей задачи в листинге 10.22 не создавало ситуации гонок. Объясните это. 8. Стандарт Posix. 1 указывает дополнительную возможность для функции sem wait: она может прерываться перехватываемым сигналом и возвращать код EINTR. Напишите тестовую программу, которая определяла бы, есть ли такая возможность в вашей реализации. Запустите эту тестовую программу с нашими реализациями, использующими FIFO (раздел 10.14), отображение в память (раздел 10.15) и семафоры System V (раздел 10.16). 9. Какая из трех реализаций sem post этой главы является функцией типа async-signal-safe (табл. 5.1)? 10. Измените решение задачи о потребителе и производителе в разделе 10.6 так, чтобы для переменной mutex использовался тип pthread mutex t, а не семафор. Заметна ли разница в скорости работы программы? И. Сравните быстродействие именованных семафоров (листинги 10.8 и 10.9) и размещаемых в памяти (листинг 10.11). ГЛАВА 11 Семафоры System V 11.1. Введение в главе 10 мы описывали различные виды семафоров, начав с: ш бинарного семафора, который может принимать только два значения: О и 1. По своим свойствам такой семафор аналогичен взаимному исключению (глава 7), причем значение О для семафора соответствует блокированию ресурса, а 1 - освобождению. Далее мы перешли к более сложному виду семафоров: семафор-счетчик, значение которого лежит в диапазоне от О до некоторого ограничения, которое, согласно Posix, не должно быть меньше 32 767. Они использовался для подсчета доступных ресурсов в задаче о производителях и потребителях, причем значение семафора соответствовало количеству доступных ресурсов. Для обоих типов семафоров операция wait состояла в ожидании изменения значения семафора с нулевого на ненулевое и последующем уменьшении этого значения на 1. Операция post увеличивала значение семафора на 1, оповещая об этом все процессы, ожидавшие изменения значения семафора. Для семафоров System V определен еще один уровень сложности: ш набор семафоров-счетчиков - один или несколько семафоров, каждый из которых является счетчиком. На количество семафоров в наборе существует ограничение (обычно порядка 25 - раздел 11.7). Когда мы говорим о семафоре System V, мы подразумеваем именно набор семафоров-счетчиков, а когда говорим о семафоре Posix, подразумевается ровно один семафор-счетчик. Для каждого набора семафоров ядро поддерживает следующую информационную структуру, определенную в файле <sys/seni.h>: struct semid ds { struct ipc perm sem perm: /* разрешения на операции */ struct sem *sem base: /*указатель на массив семафоров в наборе */ ushort sem nsems: /* количество семафоров в наборе */ time t sem otime: /* время последнего вызова semopO: */ time t sem ctime: /* время создания последнего IPC SET */ Структура 1pc perm была описана в разделе 3.3. Она содержит разрешения доступа для данного семафора. Структура sem представляет собой внутреннюю структуру данных, используемую ядром для хранения набора значений семафора. Каждый элемент набора семафоров описывается так: struct sem { ushort t semval: /* значение семафора, неотрицательно */ short sempid; /* PID последнего процесса, вызвавшего semopO. SETVAL. SETALL */ ushort t semncnt: /* количество ожидающих того, что значение семафора превысит текущее */ ushort t semzcnt: /* количество ожидающих того, что значение семафора станет равным О*/ Обратите внимание, что sem base представляет собой указатель на массив структур типа sem - по одному элементу массива на каждый семафор в наборе. Помимо текущих значений всех семафоров набора в ядре хранятся еще три поля данных для каждого семафора: идентификатор процесса, изменившего значение семафора последним, количество процессов, ожидающих увеличения значения семафора, и количество процессов, ожидающих того, что значение семафора станет нулевым. ПРИМЕЧАНИЕ- В стандарте Unix 98 данная структура не имеет имени. Приведенное выше имя (sem) взято из реализации System V. Любой конкретный семафор в ядре мы можем воспринимать как структуру semid ds, указывающую на массив структур sem. Если в наборе два элемента, мы получим картину, изображенную на рис. 11.1. На этом рисунке переменная sem nsems имеет значение 2, а каждый из элементов набора идентифицируется индексом ([0] или [1]). semid
У sem{) У semO ядро Рис. 11.1. Структуры данных ядра для набора семафоров из двух элементов 11.2. Функция semget Функция semget создает набор семафоров или обеспечивает доступ к существующему. finclude <sys/sem.h> int semget(key t key. int nsems. int oflag):
|
© 2000 - 2025 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |