- •Глава 4.
- •Многопоточность
- •Функциональность потоков
- •Потоки на пользовательском уровне и на уровне ядра
- •Другие схемы
- •4.2 Симметричная многопроцессорная обработка
- •Организация симметричной многопроцессорной системы
- •Архитектура многопроцессорных операционных систем
- •4.3. Микроядра
- •Архитектура микроядра
- •Достоинства архитектуры с микроядром
- •Производительность микроядра
- •Архитектура микроядер
- •4.4. Потоки и smp в windows 2000
- •Объекты процессов и потоков
- •Многопоточность
- •Состояния потоков
- •Поддержка подсистем операционной системы
- •Поддержка симметричной многопроцессорной обработки
- •4.5. Управление потоками и smp в solaris
- •Мотивация
- •Структура процессов
- •Выполнение потоков
- •Прерывания в роли потоков
- •4 6. Управление процессамии потоками в linux
- •4.7. Резюме, ключевые термины и контрольные вопросы
- •Контрольные вопросы
- •4.8. Рекомендуемая литература
- •4.9. Задачи
Прерывания в роли потоков
В большинстве операционных систем приняты две основные формы асинхронной деятельности: процессы и прерывания. Процессы (или потоки) взаимодействуют друг с другом и управляют использованием совместных структур данных с помощью различных примитивов, обеспечивающих взаимоисключения (когда в каждый момент времени только один процесс может выполнять определенный код или осуществлять доступ к определенным данным) и синхронизирующих их выполнение. Прерывания синхронизируются путем их предотвращения на некоторое время. В операционной системе Solaris эти две концепции объединяются в одной модели потоков ядра; прерывания в такой модели преобразуются в потоки ядра.
Эти преобразования выполняются для сокращения накладных расходов. Обработчики прерываний часто манипулируют данными, которые используются совместно с остальной частью ядра. Поэтому во время работы процедуры ядра, осуществляющей доступ к этим данным, прерывания должны быть заблокированы, даже если большинство прерываний не оказывают влияния на эти данные. Обычно для этого приходится повышать уровень приоритета прерываний, чтобы блокировать прерывания на время выполнения подпрограммы. После завершения подпрограммы уровень приоритета понижается. Все эти операции отнимают время. В многопроцессорной системе проблема усиливается.
Для обработки прерываний в системе Solaris используются потоки ядра. Как и любой другой поток ядра, поток прерывания обладает своим собственным идентификатором, приоритетом, контекстом и стеком.
Ядро управляет доступом к структурам данных и синхронизирует потоки прерываний с помощью примитивов взаимоисключений (рассматривающихся в главе 5, "Параллельные вычисления: взаимоисключения и многозадачность"). Таким образом, для обработки прерываний используются обычные методы синхронизации потоков.
Потокам прерываний присваиваются более высокие приоритеты, чем всем другим типам потоков ядра.
Если происходит прерывание, оно передается определенному процессору, а выполняющийся на этом процессоре поток закрепляется. Закрепленный поток не может перейти на другой процессор; его контекст сохраняется, и процесс приостанавливается до тех пор, пока не будет обработано прерывание. После этого процессор приступает к выполнению потока прерывания. В наличии всегда имеется запас деактивированных потоков прерываний, так что новый поток создавать не нужно. Затем исполняется поток, в котором происходит обработка прерывания. Если программе обработки понадобится доступ к структуре данных, которая каким-то образом заблокирована и используется другим потоком, поток прерывания должен ждать. Поток прерывания может быть вытеснен только другим потоком прерывания с более высоким приоритетом.
Опыт использования потоков прерываний в операционной системе Solaris свидетельствует о том, что такой подход обеспечивает производительность, превосходящую производительность традиционных методов обработки прерываний [KLEI95].
4 6. Управление процессамии потоками в linux
Процессы в Linux
В операционной системе Linux процесс, или задание, представляется структурой данных task_struct. Linux поддерживает таблицу task, представляющую собой линейный вектор указателей на каждую определенную в данный момент структуру данных task_struct. В этой структуре данных информация разбита на следующие категории.
Состояние. Состояние выполнения процесса (выполняющийся, готовый к выполнению, приостановленный, остановленный, зомби).
Информация по планированию. Информация, которая нужна операционной системе Linux для планирования процессов. Процесс может быть обычным или выполняющимся в реальном времени; кроме того, он обладает некоторым приоритетом. Процессы, выполняющиеся в реальном времени, планируются до обычных процессов; в каждой из категорий можно использовать относительные приоритеты. Счетчик ведет отсчет времени, отведенного процессу.
Идентификаторы. Каждый процесс обладает своим собственным идентификатором, а также идентификаторами пользователя и группы. Идентификатор группы используется для того, чтобы назначить группе пользователя права доступа к ресурсам.
Обмен информацией между процессами. В операционной системе Linux используется такой же механизм межпроцессного взаимодействия, как и в операционной системе UNIX SVR4, описанной в главе 6, "Взаимоблокировка и голодание".
Связи. Каждый процесс содержит в себе связи с параллельными ему процессами, с родственными ему процессами (с которыми он имеет общий родительский процесс) и связи со всеми своими дочерними процессами.
Время и таймеры. Сюда входит время создания процесса, а также количество процессорного времени, затраченного на данный процесс. С процессом а также могут быть связаны интервальные таймеры (один или несколько). Интервальный таймер задается в процессе с помощью системного вызова;после истечения периода таймера процессу отправляется соответствующий сигнал. Таймер может быть создан для одноразового или периодического использования.
Файловая система. Содержит в себе указатели на все файлы, открытые данным процессом.
Виртуальная память. Определяет отведенную данному процессу виртуальную память.
Контекст, зависящий от процессора. Информация по регистрам и стеку, составляющая контекст данного процесса. На рис. 4.18 показаны состояния выполнения процесса.
Выполняющийся. Это состояние отвечает на самом деле двум состояниям: текущий процесс либо выполняется, либо готов к выполнению.
Прерываемый. Это состояние блокировки, в котором процесс ожидает наступления события, например, завершения операции ввода-вывода, освобождения ресурса или сигнала от другого процесса.
Непрерываемый. Это состояние блокировки другого рода. Его отличие от предыдущего состоит в том, что в непрерываемом состоянии процесс непосредственно ожидает выполнения какого-то аппаратного условия, поэтому он не воспринимает никаких сигналов.
Остановленный. Процесс был остановлен и может быть продолжен только при соответствующем воздействии другого процесса. Например, процесс, который находится в состоянии отладки, может перейти в состояние остановки.
Зомби. Процесс был прекращен, но по какой-то причине его структура остается в таблице процессов.
Потоки в Linux
В операционной системе Linux новый процесс создается путем копирования атрибутов текущего процесса. Новый процесс может быть клонирован (cloned); при этом такие ресурсы, как файлы, обработчики сигналов и виртуальная память, используются совместно. Если два процесса пользуются одной и той же виртуальной памятью, они функционируют как потоки в рамках одного и того же процесса. Однако для потоков структуры данных отдельно не задаются. Таким образом, в операционной системе Linux потоки и процессы не различаются.