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

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

Операция закрытия выполняется автоматически при завершении процесса для всех семафоров, которые были им открыты. Автоматическое закрытие осуществляется как при добровольном завершении работы (вызове exit или exit), так и при принудительном (с помощью сигнала).

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

Именованный семафор удаляется из системы вызовом sein unl ink:

linclude <semaphore.h>

int sem unlink(const char *name):

/* Возвращает 0 в случае успешного завершения. -1 - в случае ошибки */ Для каждого семафора ведется подсчет процессов, в которых он является открытым (как и для файлов), и функция sein unlink действует аналогично unlink для файлов: объект пате может быть удален из файловой системы, даже если он открыт какими-либо процессами, но реальное удаление семафора не будет осуществлено до тех пор, пока он не будет окончательно закрыт.

10.3. функции sem wait и sem trywait

Функция semwait проверяет значение заданного семафора на положительность, уменьшает его на единицу и немедленно возвращает управление процессу. Если значение семафора при вызове функции равно нулю, процесс приостанавливается, до тех пор пока оно снова не станет больше нуля, после чего значение семафора будет уменьшено на единицу и произойдет возврат из функции. Ранее мы отметили, что операция проверка и уменьшение должна быть атомарной по отношению к другим потокам, работающим с этим семафором:

linclude <semaphore.h> int sem wait(sem t *sem): int semjrywait(sem t *sem):

/* Обе функции возвращают О в случае успешного завершения. -1 - в случае ошибки */ Разница между sem wai t и sem trywai t заключается в том, что последняя не приостанавливает выполнение процесса, если значение семафора равно нулю, а просто немедленно возвращает ошибку EAGAIN.

Возврат из функции sem wait может произойти преждевременно, если будет получен сигнал. При этом возвращается ошибка с кодом EINTR.

10.4. Функции sem post и sem getvalue

После завершения работы с семафором поток вызывает sempost. Как мы уже говорили в разделе 10.1, этот вызов увеличивает значение семафора на единицу и возобновляет выполнение любых потоков, ожидающих изменения значения семафора:

linclude <semaphore.h>

int sem post(sem t *sem):

int sem3getvalue(sem t *sem. int *valp):

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



Функция semgetvalue возвращает текущее значение семафора, помещая его в целочисленную переменную, на которую указывает val р. Если семафор заблокирован, возвращается либо О, либо отрицательное число, модуль которого соответствует количеству потоков, ожидающих разблокирования семафора.

Теперь мы ясно видим отличия семафоров от взаимных ис1слючений и условных переменных. Прежде всего взаимное исключение может быть разблокировано только заблокировавщим его потоком. Для семафоров такого ограничения нет: один из потоков может ожидать изменения значения семафора, чтобы потом уменьшить его с 1 до О (действие аналогично блокированию семафора), а другой поток может изменить значение семафора с О до 1, что аналогично разблокированию семафора.

Далее, поскольку любой семафор имеет некоторое значение, увеличиваемое операцией post и уменьшаемое операцией wait, поток может изменить его значение (например, увеличить с О до 1), даже если нет потоков, ожидающих его изменения. Если же поток вызывает pthread cond signal в отсутствие заблокированных при вызове pthread cond wait потоков, сигнал просто теряется.

Наконец, среди всех функций, работающих со средствами синхронизации - взаимными исключениями, условными переменными, блокировками чтения-записи и семафорами, только одна может быть вызвана из обработчика сигналов: sem post.

ПРИМЕЧАНИЕ

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

10.5. Простые примеры

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

Программа semcreate

в листинге 10.3 приведен текст программы, создающей именованный семафор. При вызове программы можно указать параметр -е, обеспечивающий исключающее создание (если семафор уже существует, будет выведено сообщение об ошибке), а параметр -i с числовым аргументом позволяет задать начальное значение семафора, отличное от 1.



Листинг 10.3. Создание именованного семафора

pxsem/semcreate.c

1 linclude unpipc.h

2 int

3 mainCint argc. char **argv)

5 int c. flags;

6 sem t *sem:

7 unsigned int value:

8 flags = 0 RDWR 0 CREAT:

9 value = 1:

10 while ( (c = GetoptCargc. argv. ei: )) != -1) {

11 switch (c) {

12 case e;

13 flags \ OJXCL:

14 break;

15 case i:

16 value - atoi(optarg):

17 break;

18 }

19 }

20 if (optind != argc - 1)

21 err quit( usage: semcreate [ -e ] [ -i initalvalue ] <name> ):

22 sem - Sem open(argv[optind]. flags. FILE M0DE, value):

23 Sem close(sem):

24 exit(O):

25 }

Создание семафора

22 Поскольку мы всегда указываем флаг ОJREAT, нам приходится вызывать semopen с четырьмя аргументами. Последние два используются только в том случае, если семафор еще не существует.

Закрытие семафора

23 Мы вызываем seni close, хотя, если бы мы не сделали этот вызов, семафор все равно закрылся бы автоматически при заверщении процесса и ресурсы системы были бы высвобождены.

Программа semunlink

Программа в листинге 10.4 удаляет именованный семафор.

Листинг 10.4. Удаление именованного семафора

pxsem/semunlink.c

1 linclude unpipc.h

2 int



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