Чтение онлайн

ЖАНРЫ

UNIX: взаимодействие процессов

Стивенс Уильям Ричард

Шрифт:
Выделение памяти под тип sem_t и открытие FIFO на чтение и запись

25-37 Мы выделяем место для типа sem_t, который содержит два дескриптора. Затем мы дважды открываем канал FIFO: один раз только на чтение, а другой — только на запись. При этом мы не хотим блокирования при вызове open, поэтому указываем флаги O_NONBLOCK при открытии очереди только для чтения (вспомните табл. 4.1). Мы также указываем флаг O_NONBLOCK при открытии канала на запись, но это предназначено для обнаружения переполнения (на тот случай, если мы попытаемся записать больше, чем позволяет PIPE_BUF). После открытия канала мы отключаем неблокируемый режим для дескриптора,

открытого на чтение.

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

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

Функция sem_close

Текст функции sem_close приведен в листинге 10.23.

11-15 Мы закрываем оба дескриптора и освобождаем память, выделенную под тип sem_t.

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

//my_pxsem_fifo/sem_close.с

1 #include "unpipc.h"

2 #include "semaphore.h"

3 int

4 mysem_close(mysem_t *sem)

5 {

6 if (sem->sem_magic != SEM_MAGIC) {

7 errno = EINVAL;

8 return(-1);

9 }

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

11 if (close(sem->sem_fd[0]) == –1 || close(sem->sem_fd[1]) == –1) {

12 free(sem);

13 return(-1);

14 }

15 free(sem);

16 return(0);

17 }

Функция sem_unlink

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

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

//my_pxsem_fifo/sem_unlink. с

1 #include "unpipc.h"

2 #include "semaphore.h"

3 int

4 mysem_unlink(const char *pathname)

5 {

6 return(unlink(pathname));

7 }

Функция sem_post

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

11-12 Мы записываем один байт в FIFO. Если канал был пуст, это приведет к возобновлению выполнения всех процессов, заблокированных в вызове read для этого канала.

Листинг 10.25. Функция sem_post

//my_pxsem_fifo/sem_post.с

1 #include "unpipc.h"

2 #include "semaphore.h"

3 int

4 mysem_post(mysem_t *sem)

5 {

6 char c;

7 if (sem->sem_magic != SEM_MAGIC) {

8 errno = EINVAL;

9 return(-1);

10 }

11 if (write(sem->sem_fd[1], &c, 1) == 1)

12 return(0);

13 return(-1);

14 }

Функция sem_wait

Последняя

функция для работы с именованными семафорами Posix — sem_wait. Ее текст приведен в листинге 10.26.

Листинг 10.26. Функция sem_wait

//my_pxsem_fifo/sem_wait.с

1 #include "unpipc.h"

2 #include "semaphore.h"

3 int

4 mysem_wait(mysem_t *sem)

5 {

6 char c;

7 if (sem->sem_magic != SEM_MAGIC) {

8 errno = EINVAL;

9 return(-1);

10 }

11 if (read(sem->sem_fd[0], &c, 1) == 1)

12 return(0);

13 return(-1);

14 }
 

11-12 Мы считываем 1 байт из канала FIFO, причем работа приостанавливается, если канал пуст.

Мы еще не реализовали функцию sem_trywait, но это можно сделать, установив флаг отключения блокировки для канала и используя обычный вызов read. Мы также не реализовали функцию sem_getvalue. В некоторых реализациях при вызове функции stat или fstat возвращается количество байтов в именованном или неименованном канале, причем оно помещается в поле st_size структуры stat. Однако это не гарантируется стандартом Posix и, следовательно, не обязательно будет работать в других системах. Пример реализации этих двух функций для работы с семафорами Posix приведен в следующем разделе.

10.15. Реализация с помощью отображения в память

Теперь займемся реализацией именованных семафоров Posix с помощью отображаемых в память файлов вместе со взаимными исключениями и условными переменными Posix. Реализация, аналогичная данной, приведена в разделе В.11.3 Обоснования стандарта IEEE 1996 [8].

ПРИМЕЧАНИЕ

Отображаемые в память файлы описаны в главах 12 и 13. Данный раздел можно отложить, с тем чтобы вернуться к нему после прочтения этих глав. 

Прежде всего приведем текст нашего заголовочного файла semaphore.h (листинг 10.27), в котором определяется фундаментальный тип sem_t.

Тип sem_t

1-7 Структура данных семафора содержит взаимное исключение, условную переменную и беззнаковое целое, в котором хранится текущее значение семафора. Как уже говорилось в связи с листингом 10.21, поле sem_magiс получает значение SEM_MAGIC при инициализации структуры.

Листинг 10.27. Заголовочный файл semaphore.h
Поделиться с друзьями: