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

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 t

1-5 Новая структура данных содержит два дескриптора, один из которых предназначен для чтения из FIFO, а другой - для записи. Для единообразия мы храним оба дескриптора в массиве из двух элементов, в котором первый дескриптор всегда открыт на чтение, а второй - на запись.

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

Функция sem open

в листинге 10.22 приведен текст функции sem open, которая создает новый семафор или открывает существующий.

Листинг 10.22. Функция sem open

niy pxsem f i f о/sem open. с

1 #include unpipc.h

2 finclude semaphore.h

3 finclude <stdarg.h> /* для произвольного списка аргументов */

4 mysem t *

5 mysem open(const char *pathname. int oflag. ... )

7 int i. flags. save errno;

8 char c:

9 nrade t mode:

10 vajist ap:

11 mysem t *sem:

12 unsigned int value:

13 if (oflag & 0 CREAT) {

14 va start(ap. oflag): /* ap инициализируется последним аргументом */

15 mode - va arg(ap. va nrade t):

16 value = va arg(ap. unsigned int):

17 va end(ap):

18 if (mkfifo(pathname, nrade) < 0) {

19 if (errno =- EEXIST && (oflag & OJXCL) == 0)

20 oflag &- -OJREAT: /* уже существует. OK */

21 else

22 return(SEMJAILED):

23 }

24 }

25 if ( (sem = manoc(sizeof(mysemJ))) == NULL)

26 return(SEM JAILED);

27 sem->semjd[0] = sem->semjd[l] = -1:

28 if ( (sem->sem fd[0] = open (pathname. 0 RDONLY 0 NONBLOCK)) < 0)

~ ~ продолжение 6



Листинг 10.22 (продолжение)

goto error:

1f ( (sem->sem fd[l] = open(pathname. 0 WRONLY 0 NONBLOCK)

goto error:

/* отключение неблокируемого режима для sem fd[0] */

if ( (flags = fcntl(sem->sem fd[0]. F GETFL. 0)) < 0)

goto error:

flags &= -0 NONBLOCK;

if (fcntl(sem->sem fd[0]. F SETFL. flags) < 0)

goto error;

if (oflag & 0 CREAT) {

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

for (i = 0: i < value:

i++)

if (write(sem->sem fd[l]. &c. 1) != 1)

goto error:

sem->sem magic = SEM MAGIC:

return(sem):

error:

save errno = errno:

if (oflag & 0 CREAT)

unlink(pathname):

/* если мы создали FIFO */

close(sem->sem fd[0]):

/* игнорируем ошибку */

close(sem->sem fd[l]);

/* игнорируем ошибку */

free(sem):

errno = save errno:

return(SEM FAILED):

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

13-17 Если при вызове указан флаг 0 CREAT, должно быть указано четыре аргумента, а не два. Мы вызываем va start, после чего переменная ар указывает на последний явно указанный аргумент (of 1 ад). Затем мы используем ар и функцию va arg для получения значений третьего и четвертого аргументов. Работу со списком аргументов переменной длины и использование нашего типа va mode t мы обсуждали в связи с листингом 5.17.

Создание нового канала FIFO

18-23 Создается новый канал FIFO, имя которого было указано при вызове функции. Как мы отмечали в разделе 4.6, эта функция возвращает ошибку EEXIST, если канал уже существует. Если при вызове sem open флаг 0 EXCL не был указан, мы пропускаем эту ошибку; но нам не нужно будет инициализировать этот канал, так что мы при этом сбрасываем флаг 0 CREAT.

Выделение памяти подтип sem t и открытие FIFO на чтение и запись

25-37 Мы выделяем место для типа sem t, который содержит два дескриптора. Затем мы дважды открываем канал FIFO: один раз только на чтение, а другой - только на запись. При этом мы не хотим блокирования при вызове open, поэтому



указываем флаги 0 NONBLOCK при открытии очереди только для чтения (вспомните табл. 4.1). Мы также указываем флаг 0 NONBLOCK при открытии канала на запись, но это предназначено для обнаружения переполнения (на тот случай, если мы попытаемся записать больше, чем позволяет PIPE BUF). После открытия канала мы отключаем неблокируемый режим для дескриптора, открытого на чтение.

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

38-42 Если мы создали семафор, его нужно проинициализировать, записав в канал FIFO val ue байтов. Если указанное при вызове значение val ue превышает определенное реализацией ограничение PIPE BUF, вызов write после переполнения FIFO вернет ошибку с кодом EAGAIN.

Функция sem close

Текст функции sem close приведен в листинге 10.23. 11-15 Мы закрываем оба дескриптора и освобождаем память, выделенную под тип sem t.

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

my pxsem fi fo/sem close.с

1 finclude unpipc.h

2 finclude semaphore.h

3 int

4 mysem close(mysem t *sem)

6 if (sem->sem magic 1= SEM MAGIC) {

7 errno = EINVAL:

8 return(-l):

10 sem->sem magic - 0: /* чтобы семафор нельзя было больше использовать */

11 if (close(sem->sem fd[0]) == -1 close(sem->sem fd[l]) == -1) {

12 free(sem):

13 return(-1):

14 }

15 free(sem):

16 return(O):

17 }

Функция sem unlink

Функция sem unl ink, текст которой приведен в листинге 10.24, удаляет из файловой системы наш семафор. Она просто вызывает unl ink.

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

my pxsem fi fо/sem un1i n к.с

1 finclude unpipc.h

2 finclude semaphore.h

3 int

4 mysem unlink(const char *pathname)

5 { продолжение



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