Добавлен: 29.10.2018
Просмотров: 48007
Скачиваний: 190
Гл а в а 2
.
Процессы и потоки
Теперь мы перейдем к подробному рассмотрению разработки и устройства операци-
онных систем. Основным понятием в любой операционной системе является процесс:
абстракция, описывающая выполняющуюся программу. Все остальное зависит от этого
понятия, поэтому крайне важно, чтобы разработчики операционных систем (а также
студенты) получили полное представление о концепции процесса как можно раньше.
Процессы — это одна из самых старых и наиболее важных абстракций, присущих
операционной системе. Они поддерживают возможность осуществления (псевдо) па-
раллельных операций даже при наличии всего одного центрального процессора. Они
превращают один центральный процессор в несколько виртуальных. Без абстракции
процессов современные вычисления просто не могут существовать. В этой главе мы
углубимся во многие подробности, касающиеся процессов и их ближайших родствен-
ников — потоков.
2.1. Процессы
Современные компьютеры, как правило, заняты сразу несколькими делами. Возможно,
люди, привыкшие к работе с компьютерами, не до конца осознают этот факт, поэтому
рассмотрим ряд примеров. Сначала представим себе веб-сервер. К нему отовсюду
приходят запросы, требующие предоставления веб-страниц. Когда приходит запрос,
сервер проверяет, нет ли нужной страницы в кэше. Если она там присутствует, он
отправляет эту страницу; если ее там нет, осуществляется запрос к диску для ее из-
влечения. Но с точки зрения центрального процессора запрос информации с диска
занимает целую вечность. За время ожидания результатов запроса информации с диска
может поступить множество других запросов. Если в системе установлено несколько
дисков, то некоторые из новых запросов или все они могут быть направлены на другие
диски задолго до того, как будет удовлетворен первый запрос. Понятно, что нужен
какой-нибудь способ, чтобы смоделировать эту параллельную работу и управлять ею.
Справиться с этим помогают процессы (и особенно потоки).
Теперь рассмотрим персональный компьютер. При запуске системы запускается мно-
жество процессов, о которых пользователь зачастую даже и не подозревает. Например,
может быть запущен процесс, ожидающий входящей электронной почты. Другой запу-
щенный процесс может принадлежать антивирусной программе и предназначаться для
периодической проверки доступности определений каких-нибудь новых вирусов. В до-
полнение к этому могут быть запущены процессы, инициированные пользователем в яв-
ном виде, — печать файлов или сброс пользовательских фотографий на USB-накопитель,
и все они работают одновременно с браузером, с помощью которого пользователь про-
сматривает Интернет. Всей этой работой нужно управлять, и здесь нам очень пригодится
многозадачная система, поддерживающая работу нескольких процессов.
112
Глава 2. Процессы и потоки
В любой многозадачной системе центральный процессор быстро переключается
между процессами, предоставляя каждому из них десятки или сотни миллисекунд.
При этом хотя в каждый конкретный момент времени центральный процессор ра-
ботает только с одним процессом, в течение 1 секунды он может успеть поработать
с несколькими из них, создавая иллюзию параллельной работы. Иногда в этом случае
говорят о псевдопараллелизме в отличие от настоящего аппаратного параллелизма
в многопроцессорных системах (у которых имеется не менее двух центральных про-
цессоров, использующих одну и ту же физическую память). Людям довольно трудно
отслеживать несколько действий, происходящих параллельно. Поэтому разработчики
операционных систем за прошедшие годы создали концептуальную модель последова-
тельных процессов, упрощающую работу с параллельными вычислениями. Эта модель,
ее применение и некоторые последствия ее применения и станут темой данной главы.
2.1.1. Модель процесса
В этой модели все выполняемое на компьютере программное обеспечение, иногда
включая операционную систему, сведено к ряду последовательных процессов, или, для
краткости, просто процессов. Процесс — это просто экземпляр выполняемой програм-
мы, включая текущие значения счетчика команд, регистров и переменных. Концепту-
ально у каждого процесса есть свой, виртуальный, центральный процессор. Разумеется,
на самом деле настоящий центральный процессор постоянно переключается между
процессами, но чтобы понять систему, куда проще думать о наборе процессов, запу-
щенных в (псевдо) параллельном режиме, чем пытаться отслеживать, как центральный
процессор переключается между программами. Это постоянное переключение между
процессами, как мы уяснили в главе 1, называется мультипрограммированием, или
многозадачным режимом работы
.
На рис. 2.1, а показан компьютер, работающий в многозадачном режиме и имеющий
в памяти четыре программы. На рис. 2.1, б показаны четыре процесса, каждый из
которых имеет собственный алгоритм управления (то есть собственный логический
счетчик команд) и работает независимо от всех остальных. Понятно, что на самом деле
имеется только один физический счетчик команд, поэтому при запуске каждого про-
цесса его логический счетчик команд загружается в реальный счетчик. Когда работа
с процессом будет на некоторое время прекращена, значение физического счетчика
команд сохраняется в логическом счетчике команд, размещаемом процессом в памяти.
На рис. 2.1, в показано, что за довольно длительный период наблюдения продвинулись
вперед все процессы, но в каждый отдельно взятый момент времени реально работает
только один процесс.
В этой главе мы будем исходить из того, что в нашем распоряжении имеет-
ся лишь один центральный процессор. Хотя все чаще такие предположения про-
тиворечат истине, поскольку новые кристаллы зачастую являются многоядер-
ными, имеющими два, четыре и большее число ядер. Многоядерным кристаллам
и мультипроцессорам будет в основном посвящена глава 8, но сейчас нам проще
думать, что в конкретный момент времени работает только один центральный
процессор. Поэтому, когда мы говорим, что центральный процессор в действитель-
ности способен в конкретный момент времени работать только с одним процес-
сом, то если он обладает двумя ядрами (или центральными процессорами), на каж-
дом из них в конкретный момент времени может запускаться только один процесс.
2.1. Процессы
113
Рис. 2.1. Компьютер: а — четыре программы, работающие в многозадачном режиме;
б — концептуальная модель четырех независимых друг от друга последовательных процессов;
в — в отдельно взятый момент активна только одна программа
Поскольку центральный процессор переключается между процессами, скорость,
с которой процесс выполняет свои вычисления, не будет одинаковой и, скорее всего,
не сможет быть вновь показана, если тот же процесс будет запущен еще раз. Поэтому
процессы не должны программироваться с использованием каких-либо жестко задан-
ных предположений относительно времени их выполнения. Рассмотрим, к примеру,
аудиопроцесс, проигрывающий музыку для сопровождения высококачественного
видео, запущенного на другом устройстве. Поскольку аудио может быть запущено
немного позднее видео, аудиопроцесс сигнализирует видеосерверу о пуске про-
игрывания, а затем перед проигрыванием аудио запускает холостой цикл 10 000 раз.
Если цикл послужит надежным таймером, то все пройдет как надо, но если же при
выполнении холостого цикла процессор решит переключиться на другой процесс,
аудиопроцесс может возобновиться, когда соответствующие кадры уже будут по-
казаны, и, к сожалению, синхронизация видео и аудио будет сбита. Когда у процесса
есть подобные критичные для его работы требования, касающиеся реального мас-
штаба времени, то через определенное количество миллисекунд должны происходить
конкретные события, и для того чтобы они произошли, должны быть предприняты
специальные меры. Но, как правило, на большинство процессов не влияют ни уста-
новленный режим многозадачности центрального процессора, ни относительные
скорости выполнения различных процессов.
Разница между процессом и программой довольно тонкая, но весьма существенная.
Здесь нам, наверное, поможет какая-нибудь аналогия. Представим себе программиста,
решившего заняться кулинарией и испечь пирог на день рождения дочери. У него есть
рецепт пирога, а на кухне есть все ингредиенты: мука, яйца, сахар, ванильный экстракт
и т. д. В данной аналогии рецепт — это программа (то есть алгоритм, выраженный в не-
кой удобной форме записи), программист — это центральный процессор, а ингредиенты
пирога — это входные данные. Процесс — это действия, состоящие из чтения рецепта
нашим кулинаром, выбора ингредиентов и выпечки пирога.
Теперь представим, что на кухню вбегает сын программиста и кричит, что его ужалила
пчела. Программист записывает, на каком месте рецепта он остановился (сохраняется
состояние текущего процесса), достает книгу советов по оказанию первой помощи
и приступает к выполнению изложенных в ней инструкций. Перед нами процессор,
переключенный с одного процесса (выпечки) на другой процесс, имеющий более вы-
сокую степень приоритета (оказание медицинской помощи), и у каждого из процессов
114
Глава 2. Процессы и потоки
есть своя программа (рецепт против справочника по оказанию первой помощи). После
извлечения пчелиного жала программист возвращается к пирогу, продолжая выполнять
действия с того места, на котором остановился.
Ключевая идея здесь в том, что процесс — это своего рода действия. У него есть про-
грамма, входные и выходные данные и состояние. Один процессор может совместно
использоваться несколькими процессами в соответствии с неким алгоритмом плани-
рования, который используется для определения того, когда остановить один процесс
и обслужить другой. В отличие от процесса программа может быть сохранена на диске
и вообще ничего не делать.
Стоит отметить, что если программа запущена дважды, то считается, что ею заняты два
процесса. Например, зачастую возможно дважды запустить текстовый процессор или
одновременно распечатать два файла, если одновременно доступны два принтера. Тот
факт, что два работающих процесса запущены от одной и той же программы, во внима-
ние не принимается, поскольку это два разных процесса. Операционная система может
позволить им использовать общий код, поэтому в памяти будет присутствовать только
одна копия этого кода, но это чисто техническая деталь, не меняющая концептуальную
ситуацию, касающуюся двух работающих процессов.
2.1.2. Создание процесса
Операционным системам необходим какой-нибудь способ для создания процессов.
В самых простых системах или в системах, сконструированных для запуска только
одного приложения (например, в контроллере микроволновой печи), появляется воз-
можность присутствия абсолютно всех необходимых процессов при вводе системы
в действие. Но в универсальных системах нужны определенные способы создания
и прекращения процессов по мере необходимости.
Существуют четыре основных события, приводящих к созданию процессов.
1. Инициализация системы.
2. Выполнение работающим процессом системного вызова, предназначенного для
создания процесса.
3. Запрос пользователя на создание нового процесса.
4. Инициация пакетного задания.
При запуске операционной системы создаются, как правило, несколько процессов.
Некоторые из них представляют собой высокоприоритетные процессы, то есть про-
цессы, взаимодействующие с пользователями и выполняющие для них определенную
работу. Остальные являются фоновыми процессами, не связанными с конкретными
пользователями, но выполняющими ряд специфических функций. Например, фо-
новый процесс, который может быть создан для приема входящих сообщений элек-
тронной почты, основную часть времени проводит в спящем режиме, активизируясь
только по мере появления писем. Другой фоновый процесс, который может быть
создан для приема входящих запросов на веб-страницы, размещенные на машине,
просыпается при поступлении запроса с целью его обслуживания. Фоновые процес-
сы, предназначенные для обработки какой-либо активной деятельности, связанной,
например, с электронной почтой, веб-страницами, новостями, выводом информации
на печать и т. д., называются демонами. Обычно у больших систем насчитываются
2.1. Процессы
115
десятки демонов. В UNIX
1
для отображения списка запущенных процессов может
быть использована программа
ps
. В Windows для этой цели может использоваться
диспетчер задач.
Вдобавок к процессам, созданным во время загрузки, новые процессы могут быть соз-
даны и после нее. Часто бывает так, что работающий процесс осуществляет системный
вызов для создания одного или более новых вспомогательных процессов. Создание
новых процессов особенно полезно, когда выполняемая работа может быть легко вы-
ражена в понятиях нескольких связанных друг с другом, но в остальном независимых
друг от друга взаимодействующих процессов. Например, если из сети выбирается
большой объем данных для последующей обработки, наверное, будет удобно создать
один процесс для выборки данных и помещения их в общий буфер, чтобы в то же са-
мое время второй процесс забирал элементы данных и проводил их обработку. Также
можно ускорить выполнение работы, если на многопроцессорной системе разрешить
каждому процессу работать на разных центральных процессорах.
В интерактивных системах пользователи могут запустить программу вводом команды
или щелчком (двойным щелчком) на значке. Любое из этих действий дает начало ново-
му процессу и запускает в нем выбранную программу. В основанных на применении
команд UNIX-системах с работающей X-оболочкой новый процесс получает окно,
в котором он был запущен. При запуске в Microsoft Windows процесс не имеет окна,
но он может создать одно или несколько окон, и в большинстве случаев так и проис-
ходит. В обеих системах пользователи могут одновременно открыть несколько окон,
в каждом из которых запущен какой-нибудь процесс. Используя мышь, пользователь
может выбрать окно и взаимодействовать с процессом, например, если потребуется,
вводить данные.
Последнее событие, приводящее к созданию процесса, применимо только к системам
пакетной обработки данных, имеющимся на больших универсальных машинах. Пред-
ставьте себе управление запасами товаров в конце рабочего дня в сети магазинов. Здесь
пользователи могут отправлять системе пакетные задания (возможно, с помощью уда-
ленного доступа). Когда операционная система решает, что у нее достаточно ресурсов
для запуска еще одного задания, она создает новый процесс и запускает новое задание
из имеющейся у нее очереди входящих заданий.
С технической точки зрения во всех этих случаях новый процесс создается за счет уже
существующего процесса, который выполняет системный вызов, предназначенный для
создания процесса. Этим процессом может быть работающий пользовательский про-
цесс, системный процесс, вызванный событиями клавиатуры или мыши, или процесс
управления пакетными заданиями. Данный процесс осуществляет системный вызов
для создания нового процесса. Этот системный вызов предписывает операционной
системе создать новый процесс и прямо или косвенно указывает, какую программу
в нем запустить.
В UNIX существует только один системный вызов для создания нового процесса —
fork. Этот вызов создает точную копию вызывающего процесса. После выполнения
системного вызова fork два процесса, родительский и дочерний, имеют единый образ
1
В этой главе под UNIX следует подразумевать практически все системы, основанные на
POSIX, включая Linux, FreeBSD, OS X, Solaris и т. д., и, за некоторым исключением, также
Android и iOS.