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

ЖАНРЫ

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

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

Шрифт:

5 {

6 int n;

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

8 errno = EINVAL;

9 return(-1);

10 }

11 if ((n = pthread_mutex_lock(&sem->sem_mutex)) != 0) {

12 errno = n;

13 return(-1);

14 }

15 *pvalue = sem->sem_count;

16 pthread_mutex_unlock(&sem->sem_mutex);

17 return(0);

18 }

Из

этой реализации видно, что семафорами пользоваться проще, чем взаимными исключениями и условными переменными.

10.16. Реализация с использованием семафоров System V

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

ПРИМЕЧАНИЕ

Семафоры System V описаны в главе 11. Этот раздел можно пропустить при первом чтении, с тем чтобы вернуться к нему по прочтении 11 главы.

Начнем, как обычно, с заголовочного файла semaphore.h (листинг 10.36), который определяет фундаментальный тип данных sem_t.

Листинг 10.36. Заголовочный файл semaphore.h

//my_pxsem_svsem/semaphore.h

1 /* фундаментальный тип данных */

2 typedef struct {

3 int sem_semid; /* идентификатор семафора System V */

4 int sem_magic; /* магическое значение, если семафор открыт */

5 } mysem_t;

6 #define SEM_MAGIC 0x45678923

7 #ifdef SEM_FAILED

8 #undef SEM_FAILED

9 #define SEM_FAILED ((mysem_t *)(-1)) /* исключаем предупреждения компилятора */

10 #endif

11 #ifndef SEMVMX

12 #define SEMVMX 32767 /* исторически сложившееся максимальное значение для семафора System V */

13 #endif

Тип данных sem_t

1-5 Мы реализуем именованный семафор Posix с помощью набора семафоров System V, состоящего из одного элемента. Структура данных семафора содержит идентификатор семафора System V и магическое число (обсуждавшееся в связи с листингом 10.21).

Функция sem_open

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

Листинг 10.37. Функция sem_open: первая часть

//my_pxsem_svsem/sem_open. с

1 #include "unpipc.h"

2 #include "semaphore.h"

3 #include <stdarg.h> /* для списков аргументов переменной длины */

4 #define MAX_TRIES 10 /*
количество попыток инициализации */

5 mysem_t *

6 mysem_open(const char *pathname, int oflag, … )

7 {

8 int i, fd, semflag, semid, save_errno;

9 key_t key;

10 mode_t mode;

11 va_list ap;

12 mysem_t *sem;

13 union semun arg;

14 unsigned int value;

15 struct semid_ds seminfo;

16 struct sembuf initop;

17 /* режим доступа для sem_open без O_CREAT не указывается; угадываем */

18 semflag = SVSEM_MODE;

19 semid = –1;

20 if (oflag & O_CREAT) {

21 va_start(ap, oflag); /* инициализируем ар последним явно указанным аргументом */

22 mode = va_arg(ap, va_mode_t);

23 value = va_arg(ap, unsigned int);

24 va_end(ap);

25 /* преобразуем в ключ, который будет идентифицировать семафор System V */

26 if ((fd = open(pathname, oflag, mode)) == –1)

27 return(SEM_FAILED);

28 close(fd);

29 if ((key = ftok(pathname, 0)) == (key_t) –1)

30 return(SEM_FAILED);

31 semflag = IPC_CREAT | (mode & 0777);

32 if (oflag & O_EXCL)

33 semflag |= IPC_EXCL;

34 /* создаем семафор System V с флагом IPC_EXCL */

35 if ((semid = semget(key, 1, semflag | IPC_EXCD) >= 0) {

36 /* OK, мы успели первыми, поэтому инициализируем нулем */

37 arg.val = 0;

38 if (semctl(semid, 0, SETVAL, arg) == –1)

39 goto err;

40 /* увеличиваем значение, чтобы sem_otime стало ненулевым */

41 if (value > SEMVMX) {

42 errno = EINVAL;

43 goto err;

44 }

45 initop.sem_num = 0;

46 initop.sem_op = value;

47 initop.sem_flg = 0;

48 if (semop(semid, &initop, 1) == –1)

49 goto err;

50 goto finish;

51 } else if (errno != EEXIST || (semflag & IPC_EXCL) != 0)

52 goto err:

53 /* иначе продолжаем выполнение */

54 }

Поделиться с друзьями: