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

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

если он еще не существует, и вернуть ошибку EEXIST, если файл существует и указан флаг 0 EXCL. Дескриптор файла затем закрывается, поскольку единственная цель создания файла была в использовании его имени при вызове ftok, преобразующей полное имя в ключ System V IPC (раздел 3.2).

Создание набора семафоров System V с одним элементом

32-33 Мы преобразуем константы 0 CREAT и 0 EXCL в соответствующие константы System V 1РС ххх и вызываем semget для создания набора семафоров System V, состоящего из одного элемента. Флаг IPC EXCL указывается всегда, чтобы можно было определить, существовал ли семафор до вызова функции или был создан ею.

Инициализация семафора

34-50 В разделе 11.2 описана фундаментальная проблема, связанная с инициализацией семафоров System V, а в разделе 11.6 приведен код, позволяющий исключить потенциальную ситуацию гонок. Здесь мы пользуемся аналогичным методом. Первый поток, который создает семафор (вспомните, что мы всегда указываем флаг IPC EXCL), инициализирует его значением О с помощью команды SETVAL при вызове semctl, а затем устанавливает запрошенное вызвавшим процессом начальное значение с помощью semop. Мы можем быть уверены, что значение sem otime семафора функцией semget устанавливается в О и будет изменено на ненулевое вызовом semop. Следовательно, любой поток, работающий с существующим семафором, будет знать, что он уже проинициализирован, если значение seffl oti те будет отлично от 0.

Проверка начального значения

40-44 Мы проверяем начальное значение, указанное вызвавшим процессом, поскольку семафоры System V обычно хранятся как беззнаковые короткие целые (unsigned short, структура зетв разделе 11.1) с максимальным значением 32 767 (раздел 11.7), тогда как семафоры Posix обычно хранятся как целые с максимально возможным размером (раздел 10.13). Константа SEMVMX определяется некоторыми реализациями как максимальное значение семафора System V, а если она не определена, то мы определяем ее равной 32 767 в листинге 10.36.

52-53 Если семафор уже существует и вызвавший процесс не указал флаг 0 EXCL, ошибка не возвращается. В этом случае программа переходит к открытию (не созданию) существующего семафора.

В листинге 10.38 приведен текст второй половины функции sem open.

Листинг 10.38. Функция sem open: вторая половина

my pxsem svsem/sem open.с

55 /*

56 * (0 CREAT не указан) или

57 * (0 CREAT без 0 EXCL и семафор уже существует).

58 * Нужно открыть семафор и проверить, что он уже проинициализирован.

59 */

60 if ( (key = ftok(pathname. 0)) == (key t) -1)

61 goto err:

62 if ( (semid = semget(key. 0. semflag)) == -1)



63 goto err:

64 arg.buf = &seminfo:

65 for (i = 0: i < MAXJRIES: i++) {

66 if (semctl(semid. 0. IPC STAT. arg) == -1)

67 goto err:

68 if (arg.buf->sem otime != 0)

69 goto finish;

70 sieep(l):

71 }

72 errno = ETIMEDOUT:

73 err:

74 save errno = errno: /* не даем вызову semctlО изменить значение errno */

75 if (semid != -1)

76 semctl(semid. 0. IPC RMID):

77 errno = save errno:

78 return(SEM JAILED):

79 finish:

80 if ( (sem = manoc(s1zeof(mysemJ))) == NULL)

81 goto err:

82 sem->sem semid = semid:

83 sem->sem magic = SEM MAGIC:

84 return(sem):

85 }

Открытие существующего семафора

55-63 Если семафор уже создан (флаг OJREAT не указан или указан, но без 0 EXCL, а семафор существует), мы открываем семафор System V с помощью semget. Обратите внимание, что в вызове sem open указывать аргумент mode не нужно, если не указан флаг 0 CREAT, но вызов semget требует указания режима доступа, даже если открывается существующий семафор. Ранее в тексте функции мы присваивали значение по умолчанию (константу SVSEM MODE из нащего заголовочного файла unpi рс. h) переменной, которую теперь передаем semget, если не указан флаг 0 CREAT.

Ожидание инициализации семафора

64-72 Проверяем, что семафор уже инициализирован, вызывая semctl с командой IPC STAT и сравнивая значение поля sem otime возвращаемой структуры с нулем.

Возврат кода ошибки

73-78 Когда возникает ошибка, мы аккуратно вызываем все последующие функции, чтобы не изменить значение errno.

Выделение памяти под sem t

79-84 Мы выделяем память под структуру sem t и помещаем в нее идентификатор семафора System V. Функция возвращает указатель на эту структуру.

Функция sem close

в листинге 10.39 приведен текст функции semjlose, которая вызывает free для освобождения динамически выделенной под структуру semt памяти.



Листинг 10.39. Функция sem close

my pxsem svsem/sem c1ose.с

1 finclude unpipc.h

2 finclude semaphore.h

3 int

4 mysem c1ose(mysem t *sem)

6 if (sem->sem ma9ic != SEM MAG1C) {

7 errno = EINVAL:

8 return(-l):

10 sem->sem magic = 0: /* на всякий случай */

11 free(sem):

12 return(O):

13 }

Функция sem unlink

Функция sem unl ink, текст которой приведен в листинге 10.40, удаляет вспомогательный файл и семафор System V, связанные с указанным ей семафором Posix.

Получение ключа System V по полному имени

8-16 Функция ftok преобразует полное имя файла в ключ System V IPC. После этого вспомогательный файл удаляется вызовом unlink (именно в этом месте кода, на тот случай, если одна из последующих функций вернет ошибку). Затем мы открываем семафор System V вызовом semget и удаляем его с помощью команды IPC RMID для semctl.

Функция sem post

в листинге 10.41 приведен текст функции sempost, которая увеличивает значение семафора.

11-16 Мы вызываем semop с операцией, увеличивающей значение семафора на 1.

Функция sem wait

Следующая функция приведена в листинге 10.42; она называется sem wai t и ожидает изменения значения семафора с нулевого на ненулевое, после чего уменьшает значение семафора на 1. 11-16 Мы вызываем semop с операцией, уменьшающей значение семафора на 1.

Листинг 10.40. Функция sem unlink

my pxsem svsem/sem unlink.с

1 finclude unpipc.h

2 finclude semaphore.h

3 int

4 mysem unlink(const char *pathname)

6 int semid:



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