Что такое процесс. Что такое сигнал. Примеры perl-кода: создание процесса, передача процессу сигналов. Что такое сигналы. Функции fork, exec, wait, waitpid. Таблица процессов. Команды free, top, ps и другие.
Данная заметка - это просто компиляция материалов из нескольких источников, с целью сбора некоторой справочной информации, которую в дальнейшем можно использовать как шпаргалку. Использованные источники указаны в конце заметки.
Что такое процесс. Определение
Процесс в Linux (как и в UNIX) - это программа, которая выполняется в отдельном виртуальном адресном пространстве.
Каждый процесс выполняется в собственном виртуальном адресном пространстве, т.е. процессы защищены друг от друга и крах одного процесса никак не повлияет на другие выполняющиеся процессы и на всю систему в целом. Один процесс не может прочитать что-либо из памяти (или записать в нее) другого процесса без "разрешения" на то другого процесса. Санкционированные взаимодействия между процессами допускаются системой.
Ядро предоставляет системные вызовы для создания новых процессов и для управления порожденными процессами. Любая программа может начать выполняться только если другой процесс ее запустит или произойдет какое-то прерывание (например, прерывание внешнего устройства).
Для создания процессов используются два системных вызова: fork и exec. Fork создает новое адресное пространство, которое полностью идентично адресному пространству основного процесса. После выполнения этого системного вызова мы получаем два абсолютно одинаковых процесса - основной и порожденный.
Теперь, когда мы уже создали процесс, мы можем запустить программу с помощью вызова exec. Параметрами функции exec является имя выполняемого файла и, если нужно, параметры, которые будут переданы этой программе. В адресное пространство порожденного с помощью fork процесса будет загружена новая программа и ее выполнение начнется с точки входа (адрес функции main)
.
Пример кода:
|
1 2 |
if (fork()==0) wait(0); else execl("ls", "ls", 0); /* порожденный процесс */ |
Теперь рассмотрим более подробно, что же делается при вызове fork:
- Выделяется память для описателя нового процесса в таблице процессов
- Назначается идентификатор процесса PID
- Создается логическая копия процесса, который выполняет fork - полное копирование содержимого виртуальной памяти родительского процесса
- Увеличиваются счетчики открытия файлов (порожденный процесс наследует все открытые файлы родительского процесса)
- Возвращается PID в точку возврата из системного вызова в родительском процессе и 0 - в процессе-потомке.
Для нормального завершение процесса используется вызов
|
1 |
exit(status); |
где status - это целое число, возвращаемое процессу-предку для его информирования о причинах завершения процесса-потомка.
Примеры perl кода
Пример 1
Простой пример создания дочернего процесса, с помощью fork:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
use strict; my $pid; if (!defined($pid = fork())) { die "cannot fork: $!"; } elsif ($pid) { # я — родительский процесс print "I am parent $pid ".$$."\n"; } else { # я — порожденннй процесс print "I am child $pid ".$$."\n"; exec("echo", "wow!"); print "Never print\n"; } exit; |
Функция fork в Perl работает, передавая свою работу системному вызову fork.
Fork возвращает PID дочернего процесса порождающему процессу. А дочерний получит значение "0". Это можно использовать, чтобы понять, в каком процессе выполняется работа. Если по каким-то причинам, новый процесс не может быть создан, например, не хватает системных ресурсов, функция вернет undef.
После создания, дочерний процесс является копией родительского. Дескрипторы файлов будут использоваться совместно.
Функция exec прекращает выполнение текущей программы и заменяет ее выполнением другой. К текущему коду процесс больше не вернется. Возврат из функции exec возможен только в том случае, если указанной программы не существует и выполнить ее невозможно. В этом случае, надо проверить $! , где будет записан код произошедшей ошибки.
Если вызов новой программы прошел благополучно, следует иметь ввиду, что код, который был расположен после exec, выполнен не будет. Не будут выполнены так же и блокиEND, DESTROY.
Результат выполнения примера:
|
1 2 3 4 |
# perl ipc.pl I am parent -2400 3664 I am child 0 -2400 wow! |
Пример 2
Пример использования функции system :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
use strict; my $pid; if (!defined($pid = fork())) { die "cannot fork: $!"; } elsif ($pid) { # я — родительский процесс print "I am parent $pid ".$$."\n"; } else { # я — порожденннй процесс print "I am child $pid ".$$."\n"; system("echo", "wow!"); print "Never print\n"; } exit; |
System так же как и exec, выполняет любую программу в системе. От exec отличается тем, что после выполнения программы возвращает управление в ту точку, откуда была вызвана функция.
Чтобы выполнить свою работу, system выполняет собственный fork, затем exec, затем дожидается завершения работы порожденного процесса.
|
1 2 3 4 5 |
# perl ipc2.pl I am parent -2452 2084 I am child 0 -2452 wow! Never print |
Пример 3
Чтобы избежать ситуаций, когда родительский процесс умирает раньше детеныша, и возникает маленький "зомби", следует писать программу таким образом, чтобы процесс-родитель всегда дожидался окончания работы детеныша. Для этого можно использовать функции wait и waitpid.
Функция wait ждет завершения дочернего процесса и возвращает PID завершенного процесса, либо -1, если дочерних процессов нет.
Функция waitpid ожидает завершения конкретного дочернего процесса. Возвращает PID завершенного процесса или -1.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
use strict; my $pid; if (!defined($pid = fork())) { die "cannot fork: $!"; } elsif ($pid) { # я — родительский процесс print "I am parent $pid $$ \n"; } else { # я — порожденннй процесс print "I am child $pid $$ \n"; exec("echo", "wow!"); print "Never print\n"; } waitpid($pid, 0); print "Parent process $$ \n"; exit; |
Результат работы скрипта:
|
1 2 3 4 5 |
# perl ipc2.pl I am parent -2688 2684 I am child 0 -2688 wow! Parent process 2684 |
Содержимое элемента таблицы процессов
В операционной системе UNIX процессы представлены довольно сложными структурами данных, которые предоставляют операционной системе всю необходимую для управления и диспетчеризации процессов информацию.
Образ процесса в UNIX:

Пример содержимого элемента таблицы процессов в системе UNIX


Сигналы
Сигнал - способ информирования процесса ядром о происшествии какого-то события. Каждый процесс реагирует на сигналы и может установить собственную реакцию на сигналы, производимые операционной системой.
Установить реакцию на поступление сигнала можно с помощью системного вызова signal:
|
1 |
func = signal(snum, function); |
snum - номер сигнала, а function - адрес функции, которая должна быть выполнена при поступлении указанного сигнала. Возвращаемое значение - адрес функции, которая будет реагировать на поступление сигнала. Вместо function можно указать ноль или единицу. Если был указан ноль, то при поступлении сигнала snum выполнение процесса будет прервано аналогично вызову
exit. Если указать единицу, данный сигнал будет проигнорирован, но это возможно не для всех процессов.
С помощью системного вызова kill можно сгенерировать сигналы и передать их другим процессам.
|
1 |
kill(pid, snum); |
Номера сигналов
| Номер | Название | Описание |
| 01 | SIGHUP | Освобождение линии (hangup). |
| 02 | SIGINT | Прерывание (interrupt). |
| 03 | SIGQUIT | Выход (quit). |
| 04 | SIGILL | Некорректная команда (illegal instruction). Не переустанавливается при перехвате. |
| 05 | SIGTRAP | Трассировочное прерывание (trace trap). Не переустанавливается при перехвате. |
| 06 | SIGIOT или SIGABRT | Машинная команда IOT. |
| 07 | SIGEMT | Машинная команда EMT. |
| 08 | SIGFPE | Исключительная ситуация при выполнении операции с вещественными числами (floating-point exception) |
| 09 | SIGKILL | Уничтожение процесса (kill). Не перехватывается и не игнорируется. |
| 10 | SIGBUS | Ошибка шины (bus error). |
| 11 | SIGSEGV | Некорректное обращение к сегменту памяти (segmentation violation). |
| 12 | SIGSYS | Некорректный параметр системного вызова (bad argument to system call). |
| 13 | SIGPIPE | Запись в канал, из которого некому читать (write on a pipe with no one to read it). |
| 14 | SIGALRM | Будильник |
| 15 | SIGTERM | Программный сигнал завершения |
| 16 | SIGUSR1 | Определяемый пользователем сигнал 1 |
| 17 | SIGUSR2 | Определяемый пользователем сигнал 2 |
| 18 | SIGCLD | Завершение порожденного процесса (death of a child). |
| 19 | SIGPWR | Ошибка питания |
| 22 | Регистрация выборочного события |
Сигналы (точнее их номера) описаны в файле signal.h
Примеры perl кода
Пример 1
В Perl применяется простая модель обработки сигналов. Существует хэш %SIG, который содержит ссылки на определенные пользователем обработчики сигналов.
После того, как происходит некоторое событие, операционная система доставляет сигнал процессу, который имеет отношение к произошедшему событию. Вызывается обработчик события, который получает на вход один аргумент - название запустившего его сигнала. Для отправки сигнала другому процессу можно использовать функцию kill. Отправителю сигнала никаких данных не возвращается.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
use strict; sub quit_handler { print "Bye!\n"; die; } $SIG{INT} = \&quit_handler; $SIG{QUIT} = \&quit_handler; sleep(15); exit; |
Если во время выполнения программы, нажать Ctrl+C - программа немедленно завершится и выведет сообщение "Bye!".
Некоторые сигналы нельзя перехватить или игнорировать, например KILL и STOP.
Пример 2
Пример использования функции kill :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
use strict; sub quit_handler { print "Bye!\n"; die; } $SIG{INT} = \&quit_handler; $SIG{QUIT} = \&quit_handler; my $pid; if (!defined($pid = fork())) { die "cannot fork: $!"; } elsif ($pid) { # я — родительский процесс print "I am parent $pid $$ \n"; } else { # я — порожденннй процесс. print "I am child $pid $$ \n"; sleep(15); print "Never print\n"; } if ($pid) { # я — родительский процесс kill('INT', $pid); print("kill child process"); }. waitpid($pid, 0); exit; |
В данной задачке, родительский процесс создает детеныша. Детеныш засыпает, а коварный родитель в это время отправляет ему сигнал на прерывание работы. Детеныш завершает свою работу, после чего это же делает и родитель.
Можно использовать kill для того, что бы проверить, жив ли процесс до сих пор. Для этого можно отправить нужному процессу сигнал "0".
Kill работает по разному в unix и windows системах. Это надо учитывать.
Как получить данные о процессе
ps
Команда ps предназначена для вывода информации о выполняемых процессах.
Поиск процессов httpd:
|
1 |
ps -f | grep httpd |
Вывод списка процессов для пользователя root:
|
1 2 3 4 |
ps -u root -f UID PID PPID C STIME TTY TIME CMD root 17705 17703 0 02:28 pts/1 00:00:00 bash -rcfile .bashrc root 18091 17705 0 04:50 pts/1 00:00:00 ps -f |
top
Команда предназначена для вывода информации о процессах в реальном времени. Процессы сортируются по максимальному занимаемому процессорному времени, но порядок сортировки можно изменить. Программа также сообщает о свободных системных ресурсах.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
top - 04:51:39 up 269 days, 18:36, 1 user, load average: 0,00, 0,00, 0,00 Tasks: 44 total, 1 running, 43 sleeping, 0 stopped, 0 zombie %Cpu(s): 0,0 us, 0,0 sy, 0,0 ni,100,0 id, 0,0 wa, 0,0 hi, 0,0 si, 0,0 st KiB Mem: 262144 total, 101984 used, 160160 free, 0 buffers KiB Swap: 0 total, 0 used, 0 free, 25948 cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 3136 552 84 S 0,0 0,2 0:05.31 init 2 root 20 0 0 0 0 S 0,0 0,0 0:00.00 kthreadd/884023 3 root 20 0 0 0 0 S 0,0 0,0 0:00.00 khelper/8840231 4 root 20 0 0 0 0 S 0,0 0,0 0:00.00 rpciod/8840231/ 5 root 20 0 0 0 0 S 0,0 0,0 0:00.00 rpciod/8840231/ 6 root 20 0 0 0 0 S 0,0 0,0 0:00.00 rpciod/8840231/ |
free
Команда free в Linux предоставляет информацию об общем использовании доступного пространства физической памяти и подкачки памяти.
|
1 2 3 4 5 |
root@185-20-224-234:/home/aninatalie/diff# free total used free shared buffers cached Mem: 262144 101736 160408 0 0 25952 -/+ buffers/cache: 75784 186360 Swap: 0 0 0 |
df
Утилита в UNIX и UNIX-подобных системах, показывает список всех файловых систем по именам устройств, сообщает их размер, занятое и свободное пространство и точки монтирования.
|
1 2 3 4 5 6 7 8 |
# df Файловая система 1K-блоков Использовано Доступно Использовано% Cмонтировано в /dev/simfs 7340032 2998684 4341348 41% / none 24643836 4 24643832 1% /dev none 24643836 996 24642840 1% /run none 24643836 0 24643836 0% /run/lock none 24643836 0 24643836 0% /run/shm none 24643836 0 24643836 0% /run/user |
w
Информация о зарегистрированных в системе пользователей.
|
1 2 3 4 |
# w 04:53:39 up 269 days, 18:38, 1 user, load average: 0,00, 0,00, 0,00 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 ppp91-79-9-111.p 02:28 0.00s 0.58s 0.58s mc |
nohup
nohup - игнорирование сигналов прерывания
|
1 |
nohup команда [аргумент] |
nohup выполняет запуск команды в режиме игнорирования сигналов. Не игнорируются только сигналы SIGHUP и SIGQUIT.
Команда nohup используется для запуска команды, которая будет игнорировать сигналы и добавлять потоки STDOUT и STDERR в файл. По умолчанию, этим файлом является либо nohup.out, либо $HOME/nohup.out.
Команда nohup позволяет процессам продолжать свою работу даже после того, как вы вышли из системы.
Можно использовать nohup для запуска команды в фоновом режиме.
kill
kill - отправка сигнала процессу. Чаще всего используется
для принудительного завершения процесса.
|
1 |
kill [-номер сигнала] PID |
где PID - идентификатор процесса, который можно узнать с помощью команды ps. Пример:
|
1 |
# kill -9 6766 |
&
Знак амперсанда можно использовать для запуска процесса в фоновом режиме:
|
1 |
# perl script/vkino_server.pl -p 3000 -r 2>~/server_log & |
uptime
Команда uptime показывает строку со следующей информацией: текущее время, время непрерывной работы системы, количество подключенных пользователей и средняя загрузка системы за последние 1, 5 и 15 минут.
|
1 2 |
# uptime 05:08:34 up 269 days, 18:52, 1 user, load average: 0,00, 0,00, 0,00 |
Использованы материалы
opennet.ru: Управление процессами в Linux
life-prog.ru: Управление процессами в операционной системе UNIX SVR4
ibm.com: Изучаем Linux, 101: Cоздание, отслеживание и уничтожение процессов
Полезные ссылки по теме процессов
ibm.com: Анатомия управления процессами в Linux
