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

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

ния значения семафора поток помечался как готовый к выполнению. Никаких изменений в работе программы не произойдет, если вместо вызвавшего sempost потока будет выполняться другой, ожидавший изменения состояния семафора (исследуйте такую ситуацию и убедитесь в этом самостоятельно).

Перечислим три главных отличия семафоров и взаимных исключений в паре с условными переменными:

1. Взаимное исключение всегда должно разблокироваться тем потоком, который установил блокировку, тогда как увеличение значения семафора не обязательно осуществляется ожидающим его изменения потоком. Это мы только что продемонстрировали на примере.

2. Взаимное исключение может быть либо заблокировано, либо разблокировано (пара состояний, аналогично бинарному семафору).

3. Поскольку состояние семафора хранится в определенной переменной, изменение его значения оказывает влияние на процессы, которые вызовут функцию wai t уже после этого изменения, тогда как при отправке сигнала по условной переменной в отсутствие ожидающих его потоков сигнал будет утерян. Взгляните на листинг 10.2 и представьте, что при первом проходе цикла производителем потребитель еще не вызвал semwait. Производитель сможет поместить объект в буфер, вызвать sem post для семафора get (увеличивая его значение с О до 1), а затем он заблокируется в вызове semwait для семафора put. Через некоторое время потребитель дойдет до цикла for и вызовет sem wa i t для переменной get, что уменьшит значение этого семафора с 1 до О, а затем потребитель приступит к обработке содержимого буфера.

ПРИМЕЧАНИЕ-

В Обосновании Posix.l (Rationale) содержится следующий комментарий по поводу добавления семафоров помимо взаимных исключений и условных переменных: Семафоры включены в стандарт в первую очередь с целью предоставить средства синхронизации выполнения процессов; эти процессы могут и не использовать общий сегмент памяти. Взаимные исключения и условные переменные описаны как средства синхронизации потоков, у которых всегда есть некоторое количество общей памяти. Оба метода широко используются уже много лет. Каждое из этих простейших средств имеет свой предпочтительный круг задач . В разделе 10.15 мы увидим, что для реализации семафоров-счетчиков с живучестью ядра требуется написать около 300 строк кода на С, использующего взаимные исключения и условные переменные. Несмотря на предпочтительность применения семафоров для синхронизации между процессами и взаимных исключений для синхронизации между потоками, и те и другие могут использоваться в обоих случаях. Следует пользоваться тем набором средств, который удобен в данном приложении.

Выше мы отмечали, что стандартом Posix описано два типа семафоров: именованные (named) и размещаемые в памяти (memory-based или unnamed). На рис. 10.4 сравниваются функции, используемые обоими типами семафоров.

Именованный семафор Posix был изображен на рис. 10.2. Неименованный, или размещаемый в памяти, семафор, используемый для синхронизации потоков одного процесса, изображен на рис. 10.5,



именованный семафор

sem open ()

неименованный семафор

sem init О

sem wait () semjrywait () sem post О sem getvalue ()

sem close () sem destroy ()

sem unlink () - ,

Рис. 10.4. Вызовы для семафоров Posix


один процесс I

Рис. 10.5. Семафор, размещенный в общей памяти двух потоков

На рис. 10.6 изображен размещенный в разделяемой памяти семафор (часть 4), используемый двумя процессами. Общий сегмент памяти принадлежит адресному пространству обоих процессов.

------. 1 семафор- , ,

процесс А

процесс В

1* *~г

один процесс

один процесс

разделяемая память

Рис. 10.6. Семафор, размещенный в разделяемой двумя процессами памяти

В этой главе сначала рассматриваются именованные семафоры Posix, а затем - размещаемые в памяти. Мы возвращаемся к задаче производителей и потребителей из раздела 7.3 и расширяем ее, позволяя нескольким производителям работать с одним потребителем, а в конце концов переходим к нескольким производителям и нескольким потребителям. Затем мы покажем, что часто используемый при реализации ввода-вывода метод множественных буферов является частным случаем задачи производителей и потребителей.

Мы рассмотрим три реализации именованных семафоров Posix: с использованием каналов FIFO, отображаемых в память файлов и семафоров System V.



10.2. Функции sem open, sem close и sem unrmk

Функция semopen создает новый именованный семафор или открывает существующий. Именованный семафор может использоваться для синхронизации выполнения потоков и процессов: linclude <semaphore.h>

sem t *sem open(const char *пдте. int oflag. ...

/* mode t nvde. unsigned int value */ ): /* Возвращает указатель на семафор в случае успешного завершения. SEM FAILED -

в случае ошибки */

Требования к аргументу пате приведены в разделе 2.2.

Аргумент oflag может принимать значения 0,0 CREAT, 0 CREAT 0 EXCL, как описано в разделе 2.3. Если указано значение 0 CREAT, третий и четвертый аргументы функции являются обязательными. Аргумент mode указывает биты разрещений доступа (табл. 2.3), а value указывает начальное значение семафора. Это значение не может превышать константу SEM VALUE MAX, которая, согласно Posix, должна быть не менее 32 767. Бинарные семафоры обычно устанавливаются в 1, тогда как семафоры-счетчики чаще инициализируются большими величинами.

При указании флага 0 CREAT (без 0 EXCL) семафор инициализируется только в том случае, если он еще не существует. Если семафор существует, ошибки не возникнет. Ошибка будет возвращена только в том случае, если указаны флаги 0 CREAT I 0 EXCL.

Возвращаемое значение представляет собой указатель на тип semt. Этот указатель впоследствии передается в качестве аргумента функциям seffl cl ose, sein wai t, sein trywait, sein post и sein getvalue.

ПРИМЕЧАНИЕ-

Кажется странным возвращать SEM FAILED в случае ошибки - нулевой указатель был бы более уместен. В ранних версиях стандарта Posix указывалось возвращаемое значение -1, и во многих реализациях константа SEM FAILED определена как

Idefine SEM FAILED ((sem t *)(-!)) В Posix.l мало говорится о битах разрешений, связываемых с семафором при его создании и открытии. Вспомните, мы говорили в связи с табл. 2.2 о том, что для именованных семафоров не нужно даже указывать флаги 0 RDONLY, 0 WRONLY и 0 RDWR. В системах, на которых мы тестируем все программы этой книги (Digital Unix 4.0В и Solaris 2.6), для работы с семафором (его открытия) необходимо иметь к нему доступ как на чтение, так и на запись. Причина, скорее всего, в том, что обе операции, выполняемые с семафором (post и wait), состоят из считывания текущего значения и последующего его изменения. Отсутствие доступа на чтение или запись в этих реализациях приводит к возвращению функцией sem open ошибки EACCESS ( Permission denied ).

Открыв семафор с помощью semopen, можно потом закрыть его, вызвав sem close:

linclude <semaphore.h> int sem close(seni t *sem):

/* Возвращает 0 в случае успешного завершения. -1 - в случае ошибки */



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.
Копирование материалов разрешено исключительно при условии цититирования.