Вход/Регистрация
UNIX: взаимодействие процессов
вернуться

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

Шрифт:
Инициализация структуры sem_t

43-57 Мы инициализируем три поля структуры sem_t: взаимное исключение, условную переменную и значение семафора. Поскольку именованный семафор Posix может совместно использоваться всеми процессами с соответствующими правами, которым известно его имя, при инициализации взаимного исключения и условной переменной необходимо указать атрибут PTHREAD_PROCESS_SHARED. Чтобы осуществить это для взаимного исключения, нужно сначала проинициализировать атрибуты, вызвав pthread_mutexattr_init, затем установить атрибут совместного использования потоками, вызвав pthread_mutexattr_setpshared, а затем проинициализировать взаимное исключение вызовом pthread_mutex_init. Аналогичные действия придется выполнить и для условной переменной. Необходимо аккуратно уничтожать переменные, в которых хранятся атрибуты, при возникновении ошибок.

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

58-61 Наконец мы помещаем в файл начальное значение семафора. Предварительно мы сравниваем его с максимально разрешенным значением семафора, которое может быть получено вызовом sysconf (раздел 10.13).

Сброс бита user-execute

62-67 После инициализации семафора мы сбрасываем бит user-execute. Это указывает на то, что семафор был успешно проинициализирован. Затем мы закрываем файл вызовом close, поскольку он уже был отображен в память и нам не нужно держать его открытым.

В листинге 10.29 приведен текст второй половины функции sem_open. Здесь возникает ситуация гонок, обрабатываемая так же, как уже обсуждавшаяся в связи с листингом 5.19.

Листинг 10.29. Функция sem_open: вторая половина

//my_pxsem_mmap/sem_open.с

69 exists:

70 if ((fd = open(pathname, O_RDWR)) < 0) {

71 if (errno == ENOENT && (oflag & O_CREAT))

72 goto again;

73 goto err;

74 }

75 sem = mmap(NULL, sizeof(mysem_t), PROT_READ | PROT_WRITE,

76 MAP_SHARED, fd, 0);

77 if (sem == MAP_FAILED)

78 goto err;

79 /* удостоверимся, что инициализация завершена */

80 for (i = 0; i < MAX TRIES; i++) {

81 if (stat(pathname, &statbuff) == –1) {

82 if (errno == ENOENT && (oflag & O_CREAT)) {

83 close(fd);

84 goto again;

85 }

86 goto err;

87 }

88 if ((statbuff.st_mode & S_IXUSR) == 0) {

89 close(fd);

90 sem->sem_magic = SEM_MAGIC;

91 return(sem);

92 }

93 sleep(1);

94 }

95 errno = ETIMEDOUT;

96 goto err;

97 pthreaderr:

98 errno = i;

99 err:

100 /* не даем вызовам unlink и munmap изменить код errno */

101 save_errno = errno;

102 if (created)

103 unlink(pathname);

104 if (sem != MAP_FAILED)

105 munmap(sem, sizeof(mysem_t));

106 close(fd);

107 errno = save_errno;

108 return(SEM_FAILED);

109 }

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

69-78 Здесь мы завершаем нашу работу, если либо не указан флаг O_CREAT, либо он указан, но семафор уже существует. В том и в другом случае мы открываем существующий семафор. Мы открываем файл вызовом open для чтения и записи, а затем отображаем его содержимое в адресное пространство процесса вызовом mmap.

ПРИМЕЧАНИЕ

Теперь легко понять, почему в Posix.1 сказано, что «обращение к копиям семафора приводит к неопределенным результатам». Если именованный семафор реализован через отображение файла в память, он отображается в адресное пространство всех процессов, в которых он открыт. Это осуществляется функцией sem_open для каждого процесса в отдельности. Изменения, сделанные одним процессом (например, изменение счетчика семафора), становятся доступны другим процессам через отображение в память. Если мы сделаем свою собственную копию структуры sem_t, она уже не будет общей для всех процессов. Хотя нам и может показаться, что вызовы срабатывают (функции для работы с семафором не будут возвращать ошибок, по крайней мере до вызова sem_close, которая не сможет отключить отображение для копии отображенного файла), с другими процессами мы при этом взаимодействовать не сможем. Однако заметьте (табл. 1.4), что области памяти с отображаемыми файлами передаются дочерним процессам при вызове fork, поэтому создание копии семафора ядром при порождении нового процесса проблем не вызовет. 

Удостоверимся, что семафор проинициализирован

79-96 Мы должны подождать, пока семафор не будет проинициализирован (если несколько потоков пытаются создать семафор приблизительно одновременно). Для этого мы вызываем stat и проверяем биты разрешений файла (поле st_mode структуры stat). Если бит user-execute снят, структура успешно проинициализирована.

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

97-108 При возникновении ошибки нужно аккуратно вернуть ее код.

  • Читать дальше
  • 1
  • ...
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: