- •Часть 4. Локальное взаимодействие процессов
- •Глава 16. Блокирование записей 89
- •12.2. Процессы, потоки и общий доступ к информации
- •12.3. Живучесть объектов ipc
- •12.4. Пространства имен
- •12.5. Действие команд fork, exec и exit на объекты ipc
- •12.6. Комментарии к примерам ipc
- •12.7. Выводы по главе 12
- •12.8. Упражнения по главе 12
- •Глава 13. Именованные и неименованные каналы
- •13.1. Введение
- •13.2. Приложение типа клиент-сервер
- •13.3. Программные каналы
- •13.4. Функции popen и pclose
- •13.5. Именованные каналы (fifo)
- •13.6. Некоторые свойства именованных и неименованных каналов
- •13.7. Один сервер, несколько клиентов
- •13.8. Последовательные и параллельные серверы
- •13.9. Ограничения программных каналов и fifo
- •13.10. Выводы по главе 13
- •13.11. Упражнения по главе 13
- •Глава 14. Программные потоки
- •14.1. Введение
- •14.2. Концепция потоков
- •14.3. Идентификация потоков
- •14.4. Создание потока
- •14.5. Завершение потока
- •Функции управления процессами и потоками
- •14.6. Установка атрибутов потока
- •14.7. Реентерабельность
- •Альтернативные версии функций, безопасные в многопоточной среде
- •14.8. Локальные данные потоков
- •14.9. Принудительное завершение потоков
- •Некоторые точки выхода, определенные стандартом Posix.1
- •14.10. Потоки и сигналы
- •14.11. Выводы по главе 14
- •14.12. Упражнения по главе 14 Глава 15. Средства синхронизации потоков
- •15.1. Введение
- •15.2. Взаимные исключения: установка и снятие блокировки
- •15.2.1. Схема производитель-потребитель
- •15.2.2. Блокирование и опрос
- •15.2.3. Предотвращение тупиковых ситуаций
- •15.3. Условные переменные
- •15.3.1. Ожидание и сигнализация
- •15.3.2. Исключение состояния гонок
- •15.4. Блокировки чтения-записи
- •15.5. Атрибуты средств синхронизации потоков
- •15.5.1. Атрибуты взаимных исключений
- •Поведение взаимных исключений различных типов
- •15.5.2. Атрибуты условных переменных
- •15.5.3. Атрибуты блокировок чтения-записи
- •15.6. Выводы по главе 15
- •15.7. Упражнения по главе 15
- •Глава 16. Блокирование записей
- •16.1. Введение
- •16.2. Блокирование записей и файлов
- •16.3. Блокирование записей с помощью fcntl по стандарту Posix
- •16.4. Рекомендательная блокировка
- •16.5. Обязательная блокировка
- •16.6. Приоритет чтения и записи Выводы по главе 16
- •Упражнения по главе 16 Глава 17. System V ipc
- •17.1. Введение
- •17.2. Ключи типа key_t и функция ftok
- •17.3. Структура ipc_perm
- •17.4. Создание и открытие каналов ipc
- •17.5. Разрешения ipc
- •17.6. Программы ipcs и ipcrm
- •17.7. Ограничения ядра
- •17.8. Выводы по главе 17
- •17.9. Упражнения по главе 17
- •Глава 18. Очереди сообщений System V
- •18.1. Введение
- •18.2. Функция msgget
- •18.3. Функция msgsnd
- •18.4. Функция msgrcv
- •18.5. Функция msgctl
- •18.6. Пример программы клиент-сервер
- •18.7. Мультиплексирование сообщений
- •18.7.1. Пример: одна очередь на приложение
- •18.7.2. Пример: одна очередь для каждого клиента
- •18.8. Ограничения, накладываемые на очереди сообщений
- •18.9. Выводы по главе 18
- •18.10. Упражнения по главе 18
- •Глава 19. Семафоры System V
- •19.1. Введение
- •19.2. Функция semget
- •19.3. Функция semop
- •19.4. Функция semctl
- •19. . Ограничения семафоров System V
- •19. . Выводы по главе 19
- •19. . Упражнения по главе 19 Глава 20. Введение в разделяемую память
- •20.1. Введение
- •20.2. Функции mmap, munmap и msync
- •20.3. Увеличение счетчика в отображаемом в память файле
- •20.4. Неименованное отображение в память
- •20.5. Обращение к объектам, отображенным в память
- •20.6. Выводы по главе 20
- •20.7. Упражнения по главе 20
- •Глава 21. Разделяемая память System V
- •21.1. Введение
- •21.2. Функция shmget
- •21.3. Функция shmat
- •21.4. Функция shmdt
- •21.5. Функция shmctl
- •21.6. Ограничения, накладываемые на разделяемую память
- •21.7. Выводы по главе 21
- •21.8. Упражнения по главе 21
Поведение взаимных исключений различных типов
|
Тип взаимного исключения |
Действия | ||
|
Повторное запирание без отпирания |
Попытка отпирания другим потоком |
Попытка отпирания незапертого взаимного исключения | |
|
PTHREAD_MUTEX_ NORMAL |
Тупиковая ситуация |
Не определено |
Не определено |
|
PTHREAD_MUTEX_ ERRORCHECK |
Возврат кода ошибки |
Возврат кода ошибки |
Возврат кода ошибки |
|
PTHREAD_MUTEX_ RECURSIVE |
Допускается |
Возврат кода ошибки |
Возврат кода ошибки |
|
PTHREAD_MUTEX_ DEFAULT |
Не определено |
Не определено |
Не определено |
В разделе 15.3мы уже говорили, что условные переменные используются только вместе со взаимными исключениями. Прежде чем заблокировать поток, функцииpthread_cond_waitиpthread_cond_timedwaitотпирают взаимное исключение, связанное с условной переменной. Это позволяет другим потокам запирать взаимное исключение, изменять условие и подавать сигнал об изменении условия. Поскольку перед изменением условия взаимное исключение должно быть захвачено, было бы неправильно использовать для этой цели рекурсивные взаимные исключения. Если рекурсивное взаимное исключение было заперто несколько раз, а затем передано функцииpthread_cond_wait, то изменение условия не будет замечено, потому что, отпирая взаимное исключение, функцияpthread_cond_waitне освобождает его.
15.5.2. Атрибуты условных переменных
Атрибуты условной переменной имеют тип pthread_condattr_t. Для их инициализации и разрушения существует пара функций, подобных соответствующим функциям для взаимных исключений.
#include<pthread.h>
int pthread_condattr_init (pthread_condattr_t *attr);
int pthread_condattr_destroy (pthread_condattr_t *attr);
/* обе функции возвращают 0 в случае успешного завершения, код ошибки – в случае неудачи */
Как и взаимные исключения, условные переменные имеют атрибут process_shared, который может принимать два значения:PTHREAD_PROCESS_PRIVATEилиPTHREAD_PROCESS_SHARED.
#include<pthread.h>
int pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared);
int pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared);
/* обе функции возвращают 0 в случае успешного завершения, код ошибки – в случае неудачи */
15.5.3. Атрибуты блокировок чтения-записи
Блокировки чтения-записи, подобно взаимным исключениям и условным переменным, также имеют атрибуты типа pthread_rwlockattr_t. Для инициализации структуры, содержащей атрибуты, следует воспользоваться двумя нижеследующими функциями:
#include<pthread.h>
int pthread_rwlockattr_init (pthread_rwlockattr_t *attr);
int pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr);
/* обе функции возвращают 0 в случае успешного завершения, код ошибки – в случае неудачи */
После инициализации объекта типа pthread_rwlockattr_tдля установки или сброса отдельных атрибутов используются специальные функции. Единственный определенный в настоящее время атрибут –PTHREAD_PROCESS_SHARED, который указывает на то, что блокировка используется несколькими процессами, а не отдельными потоками одного процесса. Две приведенные ниже функции используются для получения и установки значения этого атрибута:
#include<pthread.h>
int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared);
int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared);
/* обе функции возвращают 0 в случае успешного завершения, код ошибки – в случае неудачи */
Первая функция возвращает текущее значение в целом числе, на которое указывает аргумент pshared. Вторая функция устанавливает значение этого атрибута равнымpshared, которое может быть либоPTHREAD_PROCESS_PRIVATE, либоPTHREAD_PROCESS_SHARED.
Хотя стандарт Posix определяет всего один атрибут для блокировок чтения-записи, тем не менее, конкретные реализации могут добавлять собственные атрибуты.
