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

Сигналы

Управление процессами в Linux — это довольно обширная темя. Но все сводится к одному, мы различными способами меняем характеристики процессов. При этом мы можем преследовать совершенно разные цели: например мы можем хотеть завершить или приостановить процесс, поменять ему приоритет, заставить работать в фоне и другое.

Управление процессами может происходить по разному. Начнём наше обучение с сигналов, которые мы можем отправлять процессам.

Сигналы нужны для асинхронного оповещения процессов о разнообразных событиях в системе. Это могут быть события оборудования или события других процессов. Работа сигналов очень похожа на прерывания. То есть, если процесс получает сигнал, то он прерывает свою обычную работу, обрабатывает сигнал, а затем продолжает работать.

Сигналы от ядра поступают процессам напрямую. А сигналы от одних процессов другим поступают через ядро, то есть с помощью системных вызовов. Системный вызов, который обрабатывает сигналы называется — kill(). Его так назвали, так как большинство стандартных сигналов завершают (убивают) процесс.

Сигналы от ядра к процессам поступают напрямую. А сигналы от одних процессов к другим идут через ядро с помощью системных вызовов
Сигналы поступающие процессам

Посмотреть обзор на сигналы можно выполнив man 7 signal. Или вы можете почитать эту же документацию здесь.

Стандартные сигналы

В этой документации вы можете посмотреть список стандартных сигналов:

man 7 signal — список стандартных сигналов

Разберём некоторые из низ:

  • SIGHUP (1) — разрыв с управляющим терминалом. Процесс либо что-то предпримет (если программист об этом позаботился), либо завершится. Например, вы работаете с сервером, подключившись к нему по ssh, и вдруг связь пропадает, SSH сессия рвётся. Все ваши процессы неожиданно теряют управляющий терминал и начинают завершаться, так как получают от ядра этот сигнал.
  • SIGINT (2) — клавиатурный сигнал, срабатывает когда мы нажимаем Ctrl+c. Это штатное завершение, то есть процесс будет завершён корректно (если процесс вообще умеет завершаться корректно).
  • SIGQUIT (3) — клавиатурный сигнал, срабатывает когда мы нажимаем Ctrl+\. Аварийное завершение с выдачей отладочной информации.
  • SIGABRT (6) — аналог SIGQUIT (3). Если у процесса нет управляющего терминала, то отправить ему клавиатурный сигнал не получится, поэтому используется этот сигнал.
  • SIGKILL (9) — этот сигнал сразу завершает процесс (некорректно). И это поведение нельзя изменить, то есть программист не может сам указать программе что делать в случае получения этого сигнала.
  • SIGTERM (15) — это аналог SIGINT (2). Если у процесса нет управляющего терминала, то отправить ему клавиатурный сигнал не получится, поэтому используется этот сигнал.
  • SIGTSTP (20) — клавиатурный сигнал, когда мы нажимаем Ctrl+z. Этот сигнал приостанавливает процесс на управляющем терминале и переводит процесс на задний фон. То есть процесс переходит в состояние T (stopped by job control signal — остановленный специальным сигналом).

Утилита kill

Существует специальная команда — kill, она позволяет отправлять сигналы процессам. Тип сигнала указывается в качестве параметра в виде номера (например, -9) или имени (например, -SIGKILL). Следующим параметром нужно указать PID процесса, которому мы отправляем сигнал. Вот примеры:

$ kill -9 9898
$ kill -SIGKILL 2565

Вы можете отправить сигнал своему процессу, а если хотите отправить сигнал чужому, то нужно использовать sudo, или запускать команду kill из под пользователя root.

Передний и задний фон

Когда вы работаете в графической системе, то вы можете одновременно работать в нескольких программах. Для этого используются окна приложений. Пока вы работаете с одной программой, её окошко работает на переднем фоне. А в это время другие окна могут оставаться на заднем фоне.

Управление процессами в Linux можно применять и для того, чтобы в терминале можно было работать также, на заднем и переднем фоне. Представьте, что вы читаете справку (man) и захотели что-то попробовать. Чтобы не закрывать man, вы можете нажать Ctrl+z и приостановить man. При этом работа man не просто приостанавливается, она уходит на задний фон.

alex@deb-11:~$ man 7 signal
(тут я нажал Ctrl+z)
[1]+  Остановлен    man 7 signal

Дальше вы можете поработать в терминале. А затем, когда захотите, вернёте man на передний фон. А чтобы увидеть процессы на заднем фоне используется команда jobs:

alex@deb-11:~$ jobs
[1]+  Остановлен    man 7 signal

Разберём вывод: [1] — номер задания, + означает что это последнее приостановленное задание, а дальше идёт состояние и название процесса.

И наконец, чтобы вернуть задание на передний фон, нужно выполнить fg %<номер задания>. Или можно выполнить fg без указания номера задания, тогда на передний план вернётся задание, которое было помечено плюсиком в выводе jobs.

alex@deb-11:~$ fg %1

После выполнения последней команды, на передний план вернется работа man.

Группа переднего фона — это терминал и то что на нём сейчас выполняется. Все остальные группы — это группы заднего фона.

Работа процесса на заднем фоне

Выше я показал как остановить процесс и поместить его на задний фон. Но на заднем фоне процесс может быть не только в приостановленном состоянии. Если выполнение процесса не требует от вас каких-то интерактивных действий (никакого ввода или вывода), то можно заставить процесс выполнятся на заднем фоне. Для этого нужно выполнить bg %<номер задания>.

Например, начнём скачивание большого файла с помощью команды wget:

alex@deb-11:~$ wget https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-desktop-amd64.iso

Затем переведём процесс скачивания на задний фон, то-есть нажмём Ctrl+z. И посмотрим список заданий на заднем фоне:

alex@deb-11:~$ jobs
[1]-  Остановлен    man 7 signal
[2]+  Остановлен    wget https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-desktop-amd64.iso

Теперь, с помощью команды bg, запустим процесс на заднем фоне:

alex@deb-11:~$ bg %2
[2]+ wget https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-desktop-amd64.iso &
Вывод перенаправляется в «wget-log».

Wget должен выводить информацию о скачивании файла, но на заднем фоне запрещено выводить информацию на терминал. Именно поэтому весь вывод автоматически перенаправляется в файл — wget-log.

С помощью команды ls можем убедиться что файл скачивается (его размер увеличивается):

alex@deb-11:~$ ls -lh ubuntu-22.04.1-desktop-amd64.iso
-rw-r--r-- 1 alex alex 435M сен 26 11:30 ubuntu-22.04.1-desktop-amd64.iso

alex@deb-11:~$ ls -lh ubuntu-22.04.1-desktop-amd64.iso
-rw-r--r-- 1 alex alex 956M сен 26 11:31 ubuntu-22.04.1-desktop-amd64.iso

Выше я уже писал, что запустить процесс на заднем фоне можно только, если он не интерактивный. Например запустить остановленный man не получится:

alex@deb-11:~$ jobs
[1]+  Остановлен    man 7 signal
[2]-  Запущен          wget https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-desktop-amd64.iso &

alex@deb-11:~$ bg %1
[1]+ man 7 signal &
[1]+  Остановлен    man 7 signal

alex@deb-11:~$ jobs
[1]+  Остановлен    man 7 signal
[2]-  Запущен          wget https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-desktop-amd64.iso &

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

  • SIGTTIN (21) — остановлен за попытку чтения из stdin (на заднем фоне).
  • SIGTTOU(22) — остановлен за попытку вывода на stdout (на заднем фоне).

Если плохо помните стандартные потоки ввода вывода (stdin, stdout, stderr), то про них я писал здесь.

Изменение приоритета процесса

Приоритеты процессов Linux

В работающей системе Linux выполняется множество процессов. И каждому запущенному процессу назначается приоритет. Как ни странно, но чем больше значение приоритета, тем меньше сам приоритет. То есть, процесс с приоритетом 15 будет более приоритетным, чем процесс с приоритетом 20.

Более приоритетные процессы получают больше процессорного времени. Они более отзывчивы, выполняются более быстро. Но при этом, они сильнее нагружают процессор и замедляют все остальные процессы.

Но никакие пользователи и даже root не могут управлять приоритетами процессов. Они могут управлять другим значением — nice. Диапазон nice имеет 40 приоритетов от -20 до +19. По умолчанию, любой процесс Linux, созданный пользователем, имеет значение nice равное 0, и приоритет равный 20.

Вы можете увидеть значение nice для процессов своего пользователя и своего терминала с помощью следующей команды (утилиту ps я рассматривал здесь):

alex@deb-11:~$ ps -o pid,comm,nice,priority
    PID COMMAND          NI PRI
   5564 bash              0  20
   5761 ps                0  20

Или можно получить список всех процессов, а не только ваших:

alex@deb-11:~$ ps ax -o pid,comm,nice,priority
    PID COMMAND          NI PRI
      1 systemd           0  20
      2 kthreadd          0  20
      3 rcu_gp          -20   0
      4 rcu_par_gp      -20   0
      6 kworker/0:0H-ev -20   0
****

Разница в том, что priority — это реальный приоритет процесса в данный момент, а nice — подсказка для ядра указывающая нужно ли увеличить или уменьшить приоритет процессу.

Для пользовательских процессов, в большинстве случаев, значение priority можно рассчитать по следующей формуле: priority = 20 + nice. Таким образом, процесс с nice=3 имеет priority=23, а процесс с nice=-7 имеет priority=13.

Кроме ps, для просмотра приоритетов процессов можно использовать top и htop.

Утилита top - колонка NI
Утилита top — колонка NI
Утилита htop - колонка NI
Утилита htop — колонка NI

В Linux управление процессами, а точнее их уровнем nice, происходит с помощью команд:

  • nice — настраивает приоритет процесса перед его запуском;
  • renice — позволяет изменить приоритет уже запущенного процесса.

При этом:

  • обычный пользователь может лишь уменьшить nice своего процесса;
  • root может уменьшить или увеличить nice своего или чужого процесса.

Команда nice

Вы можете легко проверить значение nice для своего терминала (или оболочки), выполнив команду nice без каких-либо аргументов:

alex@deb-11:~$ nice
0

То есть любые команды запущенные из этой оболочки будут иметь значение nice=0.

А чтобы запустить команду с изменённым значением nice, её нужно запускать таким образом: nice <приоритет> <выполняемая команда>. Например, запустим две программы с разным приоритетом (что-бы запустить их две в одном терминале, я использую выполнение на заднем фоне):

alex@deb-11:~$ nice -2 md5sum /dev/urandom
^Z
[1]+  Остановлен    nice -2 md5sum /dev/urandom

alex@deb-11:~$ bg
[1]+ nice -2 md5sum /dev/urandom &

alex@deb-11:~$ nice -8 md5sum /dev/urandom
^Z
[2]+  Остановлен    nice -8 md5sum /dev/urandom

alex@deb-11:~$ bg
[2]+ nice -8 md5sum /dev/urandom &

alex@deb-11:~$ jobs
[1]-  Запущен          nice -2 md5sum /dev/urandom &
[2]+  Запущен          nice -8 md5sum /dev/urandom &

Теперь, с помощью htop, посмотрим на приоритеты процессов для нашего пользователя:

alex@deb-11:~$ htop -u alex
htop — демонстрация приоритетов

Как видите команды md5sum работают параллельно. Но у одной команды приоритет стал 22, а у другой 28. При этом более приоритетный процесс получает больше процессорного времени, это видно в колонке TIME+.

А если мы хотим указать отрицательное значение для nise. Другими словами, уменьшить nice и уменьшить priority, тем самым увеличив приоритет. То должны использовать двойное тире и sudo (так как обычный пользователь не имеет право запускать процессы с повышенным приоритетом):

alex@deb-11:~$ sudo nice --2 md5sum /dev/urandom
[sudo] пароль для alex:
^Z
[3]+  Остановлен    sudo nice --2 md5sum /dev/urandom

alex@deb-11:~$ bg
[3]+ sudo nice --2 md5sum /dev/urandom &

alex@deb-11:~$ jobs
[1]   Запущен          nice -2 md5sum /dev/urandom &
[2]-  Запущен          nice -8 md5sum /dev/urandom &
[3]+  Запущен          sudo nice --2 md5sum /dev/urandom &

Кстати, этот экземпляр md5sum, будет работать от пользователя root. Вот так можно посмотреть на все процессы md5sum с помощью ps:

alex@deb-11:~$ ps -C md5sum -o pid,user,comm,nice,priority,time,%cpu
    PID USER     COMMAND          NI PRI     TIME %CPU
   5791 alex     md5sum            2  22 00:13:35 90.6
   5792 alex     md5sum            8  28 00:09:31 64.3
   5802 root     md5sum           -2  18 00:06:34 98.4

Выше видно, что сильнее всего нагружает процессор процесс с уровнем nice равным -2.

Команда renice

Чтобы изменить приоритет уже работающего процесса нужно использовать команду renice -n <значение>  -p <pid>. И этой командой может пользоваться только root.

Вернём всем процессам значение nice=0:

alex@deb-11:~$ sudo renice -n 0 -p 5791
5791 (process ID) old priority 2, new priority 0

alex@deb-11:~$ sudo renice -n 0 -p 5792
5792 (process ID) old priority 8, new priority 0

alex@deb-11:~$ sudo renice -n 0 -p 5802
5802 (process ID) old priority -2, new priority 0

alex@deb-11:~$ ps -C md5sum -o pid,user,comm,nice,priority,time,%cpu
    PID USER     COMMAND          NI PRI     TIME %CPU
   5791 alex     md5sum            0  20 00:17:29 87.5
   5792 alex     md5sum            0  20 00:10:40 53.9
   5802 root     md5sum            0  20 00:11:28 98.3

А ещё вы можете изменить приоритет всех процессов определённого пользователя таким образом: sudo renice -n <значение nice> -u <имя пользователя>. Например:

alex@deb-11:~$ sudo renice -n 5 -u alex
1000 (user ID) old priority 0, new priority 5

alex@deb-11:~$ ps -C md5sum -o pid,user,comm,nice,priority,time,%cpu
    PID USER     COMMAND          NI PRI     TIME %CPU
   5791 alex     md5sum            5  25 00:18:47 85.7
   5792 alex     md5sum            5  25 00:11:58 55.1
   5802 root     md5sum            0  20 00:12:46 93.9

Обратите внимание, процессы alex стали с уровнем nice=5, а процесс root так и остался с уровнем nice=0.

Итог

Статья получилось довольно длинной. Я показал как происходит некоторое управление процессами в Linux.

Рассказал про сигналы и как их отправлять процессам с помощью клавиатуры или с помощью команды kill. Также я показал, как можно использовать передний (fg) и задний (bg) фон терминала, и этим реально можно пользоваться. Также я разобрал приоритеты процессов и как их можно менять с помощью команд nice и renice.

В статье много примеров использования команды ps. Думаю, что умение работать с этой утилитой, это очень полезный навык для системного администратора Linux.

Сводка
Управление процессами Linux
Имя статьи
Управление процессами Linux
Описание
В статье я покажу вам как осуществляется управление процессами в Linux. Вы узнаете про сигналы, передний и задний фон, и приоритеты процессов

One Reply to “Управление процессами Linux”

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *