Главная страница  Взаимодействие нетривиальных процессов 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 [ 95 ] 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

каждым 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

semval [0]

ipc perm {}

sempid [0]

semncnt [0]

sem base -

semzcnt [0]

sem nsems

semval [1]

sem otinne

sempid [1]

sem ctime

semncnt [1]

semzcnt [1]

У sem{)

У semO

ядро

Рис. 11.1. Структуры данных ядра для набора семафоров из двух элементов

11.2. Функция semget

Функция semget создает набор семафоров или обеспечивает доступ к существующему.

finclude <sys/sem.h>

int semget(key t key. int nsems. int oflag):



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 [ 95 ] 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.