Управление процессами в UNIX

Процесс — это абстракция, используемая в операционных системах UNIX и Linux для описания выполняющейся программы. Процесс представляет собой системный объект, посредством которого можно контролировать обращения программы к памяти, центральному процессору и ресурсам ввода-вывода.

Концепция, согласно которой как можно больше работы должно выполняться в контексте процессов, а не в ядре, является частью философии UNIX. Системные и пользовательские процессы подчиняются одним и тем же правилам, благодарящему управление ими осуществляется с помощью единого набора команд.

 

Атрибуты процесса

Процесс состоит из адресного пространства и набора структур данных, содержавшихся внутри ядра. Адресное пространство представляет собой совокупность страниц памяти (Страницы — это базовые блоки памяти, размер которых составляет от 1 до 8 Кбайт), которые были выделены ядром для выполнения процесса. В него загружается код процесса и используемые им библиотеки функций, а также переменные, содержимое стеков и различная вспомогательная информация, необходимая ядру во время работы процесса. Поскольку в системах UNIX и Linux поддерживается концепция виртуальной памяти, страницы адресного пространства процесса в конкретный момент времени могут находиться либо в физической памяти, либо в разделе подкачки, т.е. на диске.

В структурах данных ядра хранится всевозможная информация о каждом процессе. К наиболее важным относятся следующие сведения:

  • таблица распределения памяти;
  • текущий статус (неактивен, приостановлен, выполняется и т.п.);
  • приоритет;
  • информация об используемых ресурсах;
  • информация о файлах и сетевых портах, открытых процессом;
  • маска сигналов (запись о том, какие сигналы блокируются);
  • имя владельца процесса.

Поток выполнения, обычно именуемый просто потоком, представляет собой результат разветвления в выполнении процесса. Поток наследует многие атрибуты своего процесса (например, адресное пространство процесса), причем в рамках одного процесса могут выполняться одновременно (параллельно) сразу несколько потоков — такая модель выполнения получила название многопоточности (multithreading).

В старых однопроцессорных системах параллельное выполнение моделируется (точнее, имитируется) ядром, но в мультиядерных и многопроцессорных архитектурах потоки могут выполняться одновременно в различных ядрах. Такие многопоточные приложения, как BIND и Apache, извлекают максимальную пользу из мультиядерных систем, поскольку эти приложения могут отрабатывать несколько запросов одновременно. Все наши примеры операционных систем поддерживают многопоточный режим.

Многие характеристики процесса непосредственно влияют на его выполнение. В частности, имеет значение, сколько времени выделяется ему центральным процессором, к каким файлам он имеет доступ и т.д. В следующих подразделах рассмотрим наиболее интересные с точки зрения системного администратора характеристики процессов. Они поддерживаются во всех версиях систем UNIX и Linux.

 

Идентификатор процесса (PID)

Ядро назначает каждому процессу уникальный идентификатор2. Большинство команд и системных вызовов, работающих с процессами, требует указания конкретного идентификатора, чтобы был ясен контекст операции. Идентификаторы присваиваются по порядку по мере создания процессов.

 

Идентификатор родительского процесса (PPID)

Ни в UNIX, ни в Linux нет системного вызова, который бы инициировал новый процесс для выполнения конкретной программы. Для того чтобы породить новый процесс, существующий процесс должен клонировать сам себя. Клон может заменить выполняемую программу другой.

В операции клонирования исходный процесс называют родительским, а его клон — дочерним. Помимо собственного идентификатора, каждый дочерний процесс имеет атрибут PPID (Parent Process ID), который совпадает с идентификатором породившего его родительского процесса.

Идентификатор родительского процесса — весьма полезная информация, если приходится иметь дело с неизвестным (и, возможно, нестандартно ведущим себя) процессом. Отслеживание истоков процесса может облегчить понимание его назначения и значимости.

 

Идентификатор пользователя (UID) и текущий идентификатор пользователя (EUID)

UID (User ID) — это идентификатор пользователя, создавшего данный процесс, точнее, копия значения UID родительского процесса. Менять атрибуты процесса могут только его создатель (владелец) и суперпользователь.

EUID (Effective User ID) — это текущий пользовательский идентификатор процесса, предназначенный для того, чтобы определить, к каким ресурсам и файлам у процесса есть право доступа в данный момент. У большинства процессов значения UID и EUID одинаковы. Исключение составляют программы, у которых установлен бит смены идентификатора пользователя (setuid).

Зачем нужны два идентификатора? Просто имеет смысл разграничить понятия персонификации и прав доступа. К тому же программы с установленным битом setuid не всегда выполняются с расширенными привилегиями. В большинстве систем значение EUID можно устанавливать, чтобы предоставлять процессу дополнительные полномочия, и сбрасывать, чтобы отбирать их.

В большинстве систем хранится начальный идентификатор, т.е. копия значения EUID, который имел процесс в начальной точке. Если процесс не удалит сохраненный идентификатор, его можно будет использовать в качестве реального или текущего идентификатора. Благодаря этому "консервативно" написанная программа с установленным битом setuid может большую часть времени работать с обычными привилегиями, переходя в режим расширенных привилегий лишь в определенные моменты.

В системе Linux есть еще и нестандартный параметр FSUID, определяющий возможности работы с файловой системой, но вне ядра он используется редко и не переносится на другие системы UNIX.

 

Идентификатор группы (GID) и текущий идентификатор группы (EGID)

GID (Group ID) — это идентификатор группы, к которой принадлежит владелец процесса. Текущий идентификатор группы (Effective Group ID — EGID) связан с атрибутом GID так же, как значение EUID связано с UID, т.е. они будут отличаться в случае программы, у которой установлен бит смены идентификатора группы (setgid). В ядре назначение сохраненного GID аналогично назначению сохраненного атрибута UID.

В значительной степени атрибут GID процесса является рудиментарным. С точки зрения определения прав доступа процесс одновременно может относиться к нескольким группам. Список групп хранится отдельно от значений GID и EGID. При анализе прав доступа проверяется текущий идентификатор и дополнительный список групп, но не значение GID. Если пользователь пытается получить доступ к какому-либо ресурсу, весь список проверяется на предмет того, принадлежит ли пользователь к группе, членам которой разрешается использовать данный ресурс. Атрибут GID используется только при создании процессом новых файлов. В зависимости от установленных прав доступа в данной файловой системе новые файлы могут принимать атрибут GID создающего их процесса.

 

Приоритет и фактор уступчивости

Приоритет процесса определяет, какую долю времени центрального процессора получает программа. Ядро применяет динамический алгоритм вычисления приоритетов, учитывающий, сколько времени центрального процессора уже использовал процесс и сколько времени он ожидает своей очереди. Кроме того, учитывается заданный администратором так называемый фактор уступчивости (устанавливается с помощью команды nice), который определяет, в какой степени программа может "делиться" процессором с другими программами.

Для улучшения поддержки приложений с небольшой временной задержкой в системе Linux в традиционную модель планирования задач UNIX добавлены "классы планирования". В настоящее время существует три класса планирования, причем каждый процесс относится только к одному из них. К сожалению, классы реального времени пока не находят широкого применения, а их поддержка из командной строки оставляет желать лучшего. Все системные процессы используют традиционный планировщик, ориентированный на применение фактора уступчивости, который мы и рассматриваем в этой книге. Более подробную информацию по вопросам, связанным с планированием в реальном времени, можно найти на веб-сайте www.realtimelinuxfoundation.org.

 

Управляющий терминал

С большинством процессов, не являющихся демонами, связан управляющий терминал, который определяет базовую конфигурацию стандартных каналов ввода, вывода и ошибок. Когда пользователь запускает какую-либо программу в интерпретаторе, его терминал, как правило, становится управляющим терминалом процесса. От управляющего терминала зависит также распределение сигналов.

 

Комментарии (0)

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.