С точки зрения внешнего наблюдателя, в хорошей многозадачной ОС происходит одновременная, параллельная работа нескольких процессов. Однако понятно, что эта одновременность кажущаяся. На самом деле, если в системе работает лишь один процессор, то в каждый момент времени он выполняет команды, относящиеся только к одному из имеющихся процессов. Иллюзия параллельности создается за счет того, что процессы сменяют друг друга через малые интервалы времени, которые человек-наблюдатель не в силах отследить. Подобная организация работы называется квазипараллельным выполнением процессов.
Разумеется, если в системе имеется несколько процессоров, то может быть организовано настоящее параллельное выполнение процессов, количество которых не превышает количества процессоров. При большем числе процессов может использоваться смешанная организация, сочетающая истинную параллельность и квазипараллельность.
Важно отметить, что для большинства задач взаимодействия процессов нет разницы, какого рода параллельность используется в данной ОС. Вообще, основные проблемы управления процессами можно разбить на два уровня:
проблемы корректной и эффективной реализации параллельного (т.е. обычно квазипараллельного) выполнения процессов — это проблемы нижнего уровня;
проблемы корректного взаимодействия параллельных процессов — это проблемы верхнего уровня, при рассмотрении которых считается, что низкоуровневые проблемы реализации процессов так или иначе решены.
Такое разбиение облегчает проектирование и отладку систем, а также позволяет лучше понять существо рассматриваемых проблем.
Состояния процесса.
Состояния процесса
Любой процесс в многозадачной ОС многократно испытывает переход из одного состояния в другое.
Основных состояний всего три.
Работа (running) — в этом состоянии находится процесс, программу которого в данный момент выполняет процессор. Работающий процесс иногда удобно называть также текущим процессом.
Готовность (ready) — состояние, их которого процесс может быть переведен в состояние работы, как только это сочтет нужным сделать ОС.
Блокировка или, что то же самое, сон (sleeping, waiting) — состояние, в котором процесс не может продолжать выполнение, пока не произойдет некоторое внешнее по отношению к процессу событие.
Первые два состояния часто объединяют понятием активного состояния процесса.
Для состояний готовности и сна общее то, что процесс не работает. В чем разница между этими двумя «способами не работать»?
Готовый к выполнению процесс не выполняется только потому, что есть другие не менее готовые процессы, по мнению системы более достойные занимать сейчас процессорное время. В каждый момент времени выбор одного из готовых процессов на роль работающего определяется логикой работы ОС. Этот выбор должен обеспечивать эффективную квазипараллельную работу готовых процессов. Как решается эта задача — будет рассмотрено ниже.
В отличие от этого, спящий процесс — это всегда процесс, ожидающий некоторого конкретного события. Спящий процесс не сможет заработать, даже если процессор вдруг окажется свободным. Такой процесс, в соответствии со своей собственной логикой, ждет чего-то, что должно произойти.
Чего он может ждать? Ну, например:
завершения начатой операции синхронного ввода/вывода (т.е., например, процесс ждет нажатия клавиши Enter или окончания записи на диск);
освобождения запрошенного у системы ресурса (например, дополнительной области памяти или открытого файла);
истечения заданного интервала времени («посплю-ка я минут десять!») или достижения заданного момента времени («разбудите меня ровно в полночь!») (в обоих случаях процесс ждет сигнала от запрограммированного таймера);
сигнала на продолжение действий от другого, взаимосвязанного процесса;
сообщения от системы о необходимости выполнить определенные действия (например, перерисовать содержимое окна).
В любом из названных (и многих неназванных) случаев должно произойти некоторое событие, источник которого лежит вне данного процесса.
Чисто условно можно сказать, что если бы в вычислительную систему вдруг было добавлено еще несколько процессоров, то «готовые» процессы могли бы сразу перейти в состояние «работа», но «спящие» продолжили бы свой сон.
Разумеется, как мы видели в п. 2.5, процесс может выполнять ожидание путем циклической проверки ожидаемого условия. При этом он формально будет оставаться активным, растрачивая драгоценное процессорное время на то, что в п. 2.5.2 было названо активным ожиданием. Однако такое решение будет говорить лишь о вопиющей неквалифицированности программиста. Любая многозадачная ОС предоставляет в распоряжение прикладных программ набор функций, переводящих вызвавший их процесс в состояние сна, в котором процесс не пытается использовать процессорное время (другими словами, состояние сна есть состояние пассивного ожидания). Такие системные функции называются блокирующими. К их числу относятся функции синхронного ввода/вывода, запроса ресурсов, приостановки до заданного времени, получения сообщений и многие другие.
Поскольку ОС берет на себя блокировку, «усыпление» процесса, она должна обеспечить и его разблокировку, «пробуждение». Чтобы это стало возможным, система должна для каждого спящего процесса помнить, «чего он ждет», т.е. помнить условия пробуждения процесса. Система отслеживает все события, способные разблокировать какой-либо процесс (во многих случаях используя для этого аппаратные прерывания) и, когда для одного или сразу нескольких процессов наступает ожидаемое событие, переводит эти события из состояния сна в состояние готовности.
Рассмотрим возможные переходы между состояниями процесса, показанные на рисунке стрелками.
Переход Работа Сон представляет собой блокировку процесса, которая может произойти при вызове блокирующей системной функции.
Переход Сон Готовность — это пробуждение процесса, оно выполняется системой при возникновении соответствующего условия.
Переход Работа Готовность ранее не рассматривался. Он называется вытеснением процесса и выполняется системой, когда она принимает решение о смене текущего процесса.
Для обратного перехода Готовность Работа нет общепринятого термина. Будем называть его выбором процесса для выполнения. Отметим, что этот переход почти всегда связан либо с блокировкой, либо с вытеснением прежнего текущего процесса.
Ответьте сами на вопрос: почему «почти всегда», а не «всегда»? Какие еще возможны варианты?
Двух стрелок нет на диаграмме. Прямой переход от сна к работе нелогичен, т.к. он совмещал бы два совершенно разных действия.
Каких именно?
Переход от готовности ко сну невозможен в принципе.
Кстати, почему?
Помимо трех основных состояний, в различных ОС могут использоваться и другие состояния.
Состояние старта означает, что процесс находится на этапе создания и пока не готов вступить в работу.
Состояние завершения (в UNIX оно почти официально называется «зомби») означает, что процесс завершил свою работу, но пока присутствует в системе в виде записи о результатах и причине завершения.
Состояние приостановки (suspended) означает, что выполнение процесса временно прервано оператором (или, может быть, другим процессом) и позднее должно быть им же возобновлено.
В некоторых системах (например, в UNIX) основные состояния раздроблены на ряд более мелких: работа в системном и в пользовательском режиме, готовность в памяти и готовность на диске и т.п. Необходимый набор состояний определяется алгоритмами работы конкретной ОС.