Мы с вами рассмотрели понятие процесса, способы отображения процессов и права доступа. Но для комфортной работы в операционной системе этого мало. Необходимо еще эффективно управлять процессами. Но для реализации управления мы сначала рассмотрим строение таблицы процессов:
Родителем всех процессов в системе является процесс init. Его PID всегда 1, PPID – 0. Всю таблицу процессов можно представить себе в виде дерева, в котором корнем будет процесс init. Этот процесс хоть и не является частью ядра, но выполняет в сситеме очень важную роль, о которой мы с вами поговорим на 16-ом занятии.
Процессы, имена которых заключены в квадратные скобки, например “[keventd]” - это процессы ядра. Эти процессы управляют работой системы, а точнее такими ее частями, как менеджер памяти, планировщик времени процессора, менеджеры внешних устройств и так далее.
Остальные процессы являются пользовательскими, запущенными либо из командной строки, либо во время инициализации системы.
Жизнь каждого процесса представлена следующими фазами:
Создание процесса – на этом этапе создается полная копия того процесса, который создает новый. Например, вы запустили из интерпретатора на выполнение команду ls. Командный интерпретатор создает свою полную копию.
Загрузка кода процесса и подготовка к запуску – копия, созданная на первом этапе заменяется кодом задачи, которую необходимо выполнить и создается ее окружение – устанавливаются необходимые переменные и т.п.
Выполнение процесса
Состояние зомби – на этом этапе выполнение процесса закончилось, его код выгружается из памяти, окружение уничтожается, но запись в таблице процессов еще остается.
Умирание процесса – после всех завершающих стадий удаляется запись из таблицы процессов – процесс завершил свою работу.
Во время работы процесса, ядро контролирует его состояние, и в случае возникновения непредвиденной ситуации управляет процессом с помощью посылки ему сигнала. Процесс может воспользоваться действием по умолчанию, или, если у него есть обработчик сигнала, то он может перехватить или игнорировать сигнал. Сигналы SIGKILL и SIGSTOP невозможно не перехватить, не игнорировать.
По умолчанию возможны несколько действий:
игнорировать – продолжать работу, несмотря на то, что получен сигнал.
завершить – завершить работу процесса.
завершить + core – завершить работу процесса и создать файл в текущем каталоге с именем core, содержащий образ памяти процесса (код и данные).
остановить – приостановить выполнение процесса, но не завершать его работу и не выгружать код из памяти.
Вот список всех сигналов, существующих в системе:
Таблица 3.
Название |
Действие по умолчанию |
Значение |
SIGABRT |
Завершить + core |
Сигнал отправляется, если процесс вызывает системный вызов abort() |
SIGALRM |
Завершить |
Сигнал отправляется, когда срабатывает таймер, ранее установленный. |
SIGBUS |
Завершить + core |
Сигнал свидетельствует о некоторой аппаратной ошибке. Обычно этот сигнал отправляется при обращении к недопустимому виртуальному адресу, для которого отсутствует соответствующая физическая страница. |
SIGCHLD |
Игнорировать |
Сигнал, посылаемый родительскому процессу при завершении его потомка. |
SIGSEGV |
Завершить + core |
Сигнал свидетельствует об обращении процесса к недопустимому адресу или области памяти, для которой у процесса недостаточно привилегий доступа. |
SIGFPE |
Завершить + core |
Сигнал свидетельствует о возникновении особых ситуаций, таких как деление на 0 или переполнение операции с плавающей точкой. |
SIGHUP |
Завершить |
Сигнал посылается лидеру сеанса, связанному с управляющим терминалом, что терминал отсоединился (потеря линии). Сигнал также посылается всем процессам текущей группы при завершении выполнения лидера. Этот сигнал иногда используют в качестве простейшего средства межпроцессного взаимодействия. В частности, он применяется для сообщения демонам о необходимости обновить конфигурационную информацию. Причина выбора именно сигнала SIGHUP заключается в том, что демон по определению не имеет управляющего терминала и, соответственно, обычно не получает этого сигнала. |
SIGILL |
Завершить + core |
Сигнал посылается ядром, если процесс попытается выполнить недопустимую инструкцию. |
SIGINT |
Завершить |
Сигнал посылается ядром всем процессам при нажатии клавиши прерывания (<CTRL>+<C>) |
SIGKILL |
Завершить |
Сигнал, при получении которого выполнение процесса прекращается. Этот сигнал нельзя не перехватить, не проигнорировать. |
SIGPIPE |
Завершить |
Сигнал посылается при попытке записи в сокет, получатель данных которого завершил выполнение или закрыл файловый указатель на сокет. |
SIGPOLL |
Завершить |
Сигнал отправляется при наступлении определенного события для устройства, которое является опрашиваемым (например, получен пакет по сети) |
SIGPWR |
Игнорировать |
Сигнал генерируется при угрозе потери питания. Обычно он отправляется, когда питание системы переключается на источник бесперебойного питания (UPS). |
SIGQUIT |
Завершить |
Сигнал посылается всем процессам текущей группы при нажатии клавиш <CTRL>+<\>. |
SIGSTOP |
Остановить |
Сигнал отправляется всем процессам текущей группы при нажатии пользователем клавиш <CTRL>+<Z>. Получение сигнала вызывает останов выполнения процесса. |
SIGSYS |
Завершить + core |
Сигнал отправляется ядром при попытке осуществления процессом недопустимого системного вызова. |
SIGTERM |
Завершить |
Сигнал обычно представляет своего рода предупреждение, что процесс вскоре будет уничтожен. Этот сигнал позволяет процессу соответствующим образом “подготовиться к смерти” - удалить временные файлы, завершить необходимые транзакции и т.д. Команда kill по умолчанию отправляет именно этот сигнал. |
SIGTTIN |
Остановить |
Сигнал генерируется ядром (драйвером управляющего терминала) при попытке процесса фоновой группы осуществить чтение с управляющего терминала. |
SIGTTOU |
Остановить |
Сигнал генерируется ядром (драйвером терминала) при попытке процесса фоновой группы осуществить запись на управляющий терминал. |
SIGUSR1 |
Завершить |
Сигнал предназначен для прикладных задач как простейшее средство межпроцессного взаимодействия. |
SIGUSR2 |
Завершить |
Сигнал предназначен для прикладных задач как простейшее средство межпроцессного взаимодействия. |
Немаловажную роль в жизни процессов играет также планировщик – это часть ядра, ответственная за многозадачность системы. Ведь в единицу времени на одном процессоре может выполняться только одна задача. Именно планировщик определяет, какой из запущенных процессов первым будет выполняться, какой вторым. Для этого у каждого процесса существует еще один параметр, называемый приоритетом. Для того, чтобы посмотреть приоритет процессов, нам необходимо использовать уже знакомую команду ps с параметром -l (long – расширенный вывод):
Рисунок 57.
Во время своей работы, планировщик в первую очередь ставит на выполнение задачи с меньшим приоритетом. Так, приоритетом 0, обладают только критические системный задачи, а отрицательным приоритетом – процессы ядра. Задачам с большим приоритетом достается меньше процессорного времени и потому, работают они как правило, медленнее, и потребляют намного меньше системных ресурсов.