Рейтинг@Mail.ru

NetCloud

Простыми словами о сетевых технологиях

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

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

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

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

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

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

 

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

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

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

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

Когда система загружается, ядро самостоятельно запускает несколько процессов. Наиболее важный из них — демон init, идентификатор которого всегда равен 1. Демон init отвечает за выполнение сценариев запуска системы. Все процесса, кроме тех, что создаются ядром, являются потомками демона init. 

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

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

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

 

Жизненный цикл процесса

Создание процесса — это переход процесса из состояния «Новый» в состояние «Готов». В момент создания процесса операционная система подготавливает структуру данных для него. Новому процессу присваивается собственный PID, и учет ресурсов ведется независимо от предка. Тот факт, что процесс существует — еще не дает ему права на использование ресурсов центрального процессора.
zhiznennyy-cikl-processa

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

Из состояния «Запущен» есть два пути:

  1. Таймаут — процесс поработал и освободил ресурсы процессора (перешел в очередь)
  2. Ожидание — процесс переведен в режим ожидания, где ждет некоего сигнала

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

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

После того как процесс завершился — он уничтожается.

Зомби — это процесс, который закончил выполняться, но информация об этом еще не поступила родительскому процессу. Процесс при завершении высвобождает все свои ресурсы (за исключением PID) и становится «зомби» — пустой записью в таблице процессов, хранящий код завершения для родительского процесса.

zombie

Все процессы выстраиваются в очередь на выполнение команд. При этом существует несколько очередей в зависимости от статуса процесса: очередь готовых и очередь заблокированных. По истечении работы процесс переходит в начало очередь и вновь ждет своего момента для доступа к ресурсам центрального процессора.

ochered-processov

 

Работа с процессами в Linux

Просмотреть список всех процессов, выполняемых в текущий момент времени можно с помощью команды ps. С помощью команды ps можно получить информацию об идентификаторах, приоритете и управляющем терминале того или иного процесса. Она также позволяет выяснить объем оперативной памяти, который использует процесс, сколько времени центрального процессора заняло его выполнение, а также состояние процесса (выполняется, остановлен, простаивает и т.д.). Получить список всех процессов можно с помощью следующей команды:

user@ubuntu$ ps aux

Ключ используется для вывода всех процессов, ключ x — отображает процессы, отсоединенные от терминала, ключ u — обеспечивает фильтрование по имени или идентификатору пользователя, который запустил программу.





ps-aux

Значение столбцов при выводе команды ps aux:

  1. USER — имя владельца процесса
  2. PID — идентификатор процесса
  3. %CPU — доля времени центрального процессора, которая тратится на данный процесс (в процентах)
  4. %MEM — часть реальной памяти, которая тратится на данный процесс (в процентах)
  5. VSZ — виртуальный размер процесса
  6. RSS — количество страниц памяти
  7. TTY — идентификатор управляющего терминала
  8. STAT — текущий статус процесса (R-выполняется, D-ожидает записи на диск, S-неактивен, T-приостановлен, Z-зомби)
  9. TIME — количество времени центрального процессора, затраченное на выполнение данного процесса
  10. COMMAND — имя и аргументы команды

Ниже в сокращенном виде показаны результаты работы команды ps lax. Обратите внимание на дополнительные поля PPID (идентификатор родительского процесса), NI (фактор уступчивости), WCHAN (ресурс, которого ожидает процесс).

ps-lax

NI по сути отображает приоритет процесса. Чем ниже значение — тем приоритетней он будет выполняться процессором. Значение варьируются от -20 до 20.

Очень удобно искать идентификатор процесса с помощью связки команд ps и grep. PS выводит список процессов, после чего передает управление команде grep, которая в свою очередь выделяет из списка искомый процесс. Пример: найдем PID для процесса cron.

ps-grep
Как видно PID для процесса cron равен 879.

Команда ps позволяет сделать только разовый «снимок» системы. Для динамического отслеживания процессов используют команду top.

top

Наиболее активные процессы находятся вверху. Команда top отображает также статистику по статусам процессов, объем используемых ресурсов ЦПУ и оперативной памяти.

Сигналы — это запросы на прерывания, реализуемые на уровне процессов.

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

Дамп памяти — это файл, содержащий образ памяти процесса

Процедура вызова обработчика называется перехватом сигнала. Когда выполнение обработчика завершается, процесс возобновляется с той точки, где был получен сигнал.

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

Определено свыше тридцати разных сигналов, и они находят самое разное применение. Самые распространенные из них:

  1. KILL — безусловное завершение процесса на уровне ядра
  2. STOP — приостанавливает выполнение процесса
  3. CONT — возобновляет выполнение процесса
  4. TSTP — генерируется при нажатии CTRL + Z, приостанавливает процесс пользователем
  5. TERM — запрос на завершение программы (процесс осуществляет очистку и нормально завершается)
  6. QUIT — то же самое, что и TERM + создается дамп памяти
  7. HUP — команда сброса
  8. BUS — ошибка на шине (указывает на неправильное обращение к памяти)
  9. SEGV — ошибка на сегментации (указывает на неправильное обращение к памяти)

Сигналы KILL и STOP нельзя ни перехватить, ни заблокировать, ни проигнорировать.

Команда kill используется для отправки сигналов процессу. Kill имеет следующий синтаксис:

user@ubuntu$ kill [-сигнал] PID

Для примера уничтожим процесс cron. Ранее мы выяснили, что его PID = 879.

user@ubuntu$ kill -KILL 879

kill-cron

Как видим процесс cron убран. Сигналы типа kill надо посылать с правами суперпользователя. Также перед тем, как убивать cron я убрал строчку respawn в конфигурационном файле cron.conf, который находится в папке /etc/init/cron.conf.

Напоследок расскажу про еще одну интересную вещь. Upstart — это система инициализации ОС, которая управляет запуском демонов в течении загрузки системе. Хранятся конфигурационные файлы Upstart в папке /etc/init. Существует несколько команд для работы с Upstart.

user@ubuntu$ status [имя процесса] — статус процесса

user@ubuntu$ start [имя процесса] — запуск процесса

user@ubuntu$ stop [имя процесса] — остановка процесса

user@ubuntu$ restart [имя процесса] — рестарт процесса


 

  • Обсуждение приветствуется, оставляйте комментарии. Чем я могу дополнить данную статью?