- •Часть 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
14.1. Введение
В предыдущих главах мы обсуждали процессы. Мы рассмотрели среду окружения процессов в Unix, взаимоотношения между процессами и способы управления ими.
В этой главе мы продолжим изучение внутреннего устройства процессов и узнаем, как можно использовать несколько потоков управления (threads) для решения нескольких задач в рамках единственного процесса. Все потоки внутри процесса имеют доступ к одним и тем же компонентам процесса, таким как файловые дескрипторы или переменные.
Всякий раз при попытке организовать одновременный доступ нескольких пользователей к одному и тому же ресурсу приходится сталкиваться с проблемой согласования доступа. В конце этой главы мы рассмотрим механизмы синхронизации потоков, которые позволяют предотвратить доступ разных потоков к разделяемым ресурсам, находящимся в несогласованном состоянии.
14.2. Концепция потоков
Типичный процесс в Unix можно представить как имеющий единственный поток управления – каждый процесс в один момент времени решает только одну задачу. При использовании нескольких потоков управления мы можем спроектировать приложение таким образом, что оно будет решать одновременно несколько задач в рамках единственного процесса, где каждый поток решает отдельную задачу. Такой подход имеет следующие преимущества:
мы можем значительно упростить код, обрабатывающий асинхронные события, привязав события каждого типа к отдельному потоку. В результате каждый поток может обслуживать события своего типа, используя синхронную модель программирования, которая намного проще асинхронной;
чтобы организовать совместный доступ нескольких процессов к одним и тем же ресурсам, таким как разделяемая память или файловые дескрипторы, необходимо использовать достаточно сложные механизмы синхронизации, предоставляемые операционной системой (об этом в главах 15 и 17). Потоки же, в отличие от процессов, автоматически получают доступ к одному и тому же адресному пространству и файловым дескрипторам;
решение некоторых задач можно разбить на более мелкие подзадачи, что может дать прирост производительности программы. Однопоточный процесс, выполняющий решение нескольких задач, неявно вынужден решать их последовательно, поскольку он имеет только один поток управления. При наличии нескольких потоков управления независимые друг от друга задачи могут решаться одновременно отдельными потоками. Две и более задач могут решаться одновременно только при условии, что они не зависят друг от друга;
аналогичным образом, интерактивные программы, могут сократить время отклика на действия пользователя, используя многопоточную модель для того, чтобы отделить обработку ввода-вывода пользователя от других частей программы.
У многих многопоточное программирование ассоциируется с многопроцессорными системами. Однако преимущества многопоточной модели проявляют себя, даже если программа работает в однопроцессорной системе. Независимо от количества процессоров, программа может быть упрощена благодаря многопоточной модели, поскольку количество процессоров не влияет на структуру программы. Кроме того, в то время как однопоточный процесс вынужден периодически простаивать при последовательном решении нескольких задач, многопоточный процесс может повысить производительность и в однопроцессорной системе, так как часть потоков могут продолжать работу, когда другие приостановлены в ожидании наступления некоторых событий.
Поток содержит набор информации, необходимой для представления контекста исполнения внутри процесса. Сюда включаются идентификатор потока, который позволяет различать потоки внутри процесса, набор значений в регистрах процессора, стек, приоритет, маска сигналов, переменная errno (раздел 1.9) и дополнительные данные, специфичные для потока (раздел 12.6). Все компоненты процесса, включая исполняемый код программы, глобальные переменные и динамическую память, стеки и файловые дескрипторы, могут совместно использоваться различными потоками этого процесса.
Интерфейс потоков, о котором мы будем говорить, известен под именем “pthreads” и определяется стандартом Posix.1-2001.
