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

В статье я покажу вам как осуществляется управление процессами в Linux. Вы узнаете про сигналы (kill), передний и задний фон (fg, bg, jobs), и приоритеты процессов (nice, renice). Управление процессами в Linux — это довольно обширная темя. Но все сводится к одному, мы различными способами меняем характеристики процессов. При этом мы можем преследовать совершенно разные цели: например мы можем хотеть завершить или приостановить процесс, поменять ему приоритет, заставить работать в фоне и другое.

🕒 8 мин.

Сигналы

Что такое сигналы

Все примеры в данной статье были сделаны в системе Debian 13, в других системах вывод может немного отличаться. Но работать всё должно похожим образом.

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

Сигналы от ядра поступают процессам напрямую, а сигналы от одних процессов другим поступают через ядро с помощью системных вызовов. Системный вызов, который обрабатывает сигналы называется — 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 позволяет отправлять сигналы процессам. В качестве параметров нужно указать номер сигнала (или имя) и PID процесса, например:

$ kill -9 9898
$ kill -SIGKILL 9898

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

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

Приостанавливаем процесс перемещая на задний фон

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

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

$ man 7 signal
(нажимаем Ctrl+z)
[1]+  Остановлен    man 7 signal
  • [1] — номер задания, + означает что это последнее приостановленное задание, дальше идёт состояние и название процесса.

Дальше вы можете поработать в терминале, а когда захотите, вернёте man на передний план.

$ jobs
[1]+  Остановлен    man 7 signal

$ fg %1
  • С помощью jobs — смотрим список остановленных заданий.
  • С помощью fg — возвращаем задание на передний план. Можно не указывать номер задания, тогда вернётся на передний план последнее приостановленное задание.

Запускаем процесс в фоне

Выше я показал как остановить процесс и поместить его в фон. Но в фоне процесс может быть не только в приостановленном состоянии а ещё и работать. Но только если выполнение процесса не требует от вас каких-то интерактивных действий (ввода или вывода).

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

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

А вот скачивание большого файла можно перевести в фон. Для этого нужно выполнить bg %<номер задания>.

$ wget https://releases.ubuntu.com/24.04/ubuntu-24.04.4-live-server-amd64.iso

(нажимаем Ctrl+z)
[2]+  Остановлен    wget https://releases.ubuntu.com/24.04/ubuntu-24.04.4-live-server-amd64.iso

$ bg %2
[2]+ wget https://releases.ubuntu.com/24.04/ubuntu-24.04.4-live-server-amd64.iso &
alex@Copy-of-VM-debian-13:~$
Вывод перенаправляется в «wget-log».
  • wget должен выводить информацию о скачивании файла, но в фоне это запрещено. Поэтому вывод автоматически перенаправляется в файл — wget-log.

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

$ ls -lh ubuntu-24.04.4-live-server-amd64.iso
-rw-rw-r-- 1 alex alex 299M мар 24 10:32 ubuntu-24.04.4-live-server-amd64.iso

$ ls -lh ubuntu-24.04.4-live-server-amd64.iso
-rw-rw-r-- 1 alex alex 329M мар 24 10:32 ubuntu-24.04.4-live-server-amd64.iso

Отвязываем процесс от терминала

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

Делается это следующим образом.

  1. Останавливаем процесс (который работал не в фоне) нажатием Ctrl+z.
  2. Запускаем процесс в фоне командой bg.
  3. Чтобы отвязать процесс от терминала выполняем disown %1.

Команда disown блокирует отправку системного сигнала SIGHUP (1).

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

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

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

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

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

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

$ ps -o pid,comm,nice,priority
    PID COMMAND          NI PRI
   9631 bash              0  20
  11187 man               0  20
  11196 pager             0  20
  11649 ps                0  20

Можно получить список всех процессов добавив опции ax:

$ ps ax -o pid,comm,nice,priority
    PID COMMAND          NI PRI
      1 systemd           0  20
      2 kthreadd          0  20
      3 pool_workqueue_   0  20
      4 kworker/R-kvfre -20   0
      5 kworker/R-rcu_g -20   0
      6 kworker/R-sync_ -20   0
(вывод сократил)

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

Для пользовательских процессов, в большинстве случаев, значение priority можно рассчитать по формуле: priority = 20 + nice

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

Назначение приоритетов можно выполнять с помощью команд:

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

При этом:

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

Команда nice

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

$ nice
0
  • Любые процессы запущенные в этой оболочки будут иметь nice=0.

Чтобы запустить процесс с изменённым nice, его нужно запускать таким образом: nice <приоритет> <выполняемая команда>. Например, запустим две программы с разным приоритетом:

$ nice -2 md5sum /dev/urandom

(нажимаем Ctrl+z)
[2]+  Остановлен    nice -2 md5sum /dev/urandom

$ bg %2
[2]+ nice -2 md5sum /dev/urandom &

$ nice -8 md5sum /dev/urandom

(нажимаем Ctrl+z)
[3]+  Остановлен    nice -8 md5sum /dev/urandom

$ bg %3
[3]+ nice -8 md5sum /dev/urandom &

$ jobs
[1]+  Остановлен    man 7 signal
[2]   Запущен          nice -2 md5sum /dev/urandom &
[3]-  Запущен          nice -8 md5sum /dev/urandom &

Теперь, с помощью htop, посмотрим на процессы:

$ htop -u alex

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

А если мы хотим указать отрицательное значение для nise, тем самым увеличив приоритет. То должны использовать двойное тире и sudo:

$ sudo nice --2 md5sum /dev/urandom

(нажимаем Ctrl+z)
[4]+  Остановлен    sudo nice --2 md5sum /dev/urandom

$ bg %4
[4]+ sudo nice --2 md5sum /dev/urandom &

Кстати, этот экземпляр md5sum, будет работать от пользователя root.

$ ps -C md5sum -o pid,user,comm,nice,priority,time,%cpu
    PID USER     COMMAND          NI PRI     TIME %CPU
  11766 alex     md5sum            2  22 00:07:14 90.4
  11777 alex     md5sum            8  28 00:06:08 87.0
  11853 root     md5sum           -2  18 00:00:45 49.0
  • Постепенно процесс с повышенным приоритетом получит больше процессорного времени, чем было у 2-ух предыдущих процессов.

Команда renice

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

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

$ sudo renice -n 0 -p 11766
$ sudo renice -n 0 -p 11777
$ sudo renice -n 0 -p 11853

$ ps -C md5sum -o pid,user,comm,nice,priority,time,%cpu
    PID USER     COMMAND          NI PRI     TIME %CPU
  11766 alex     md5sum            0  20 00:10:17 86.0
  11777 alex     md5sum            0  20 00:07:13 65.7
  11853 root     md5sum            0  20 00:04:29 81.9

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

$ sudo renice -n 5 -u alex


$ ps -C md5sum -o pid,user,comm,nice,priority,time,%cpu
    PID USER     COMMAND          NI PRI     TIME %CPU
  11766 alex     md5sum            5  25 00:10:46 84.5
  11777 alex     md5sum            5  25 00:07:44 65.5
  11853 root     md5sum            0  20 00:05:04 80.9
  • Процессы alex стали с уровнем nice=5, а процесс root так и остался nice=0.

Итог

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

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

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

Если понравилась статья, подпишись на мой канал в VK или Telegram.

Мы используем cookie-файлы для наилучшего представления нашего сайта. Продолжая использовать этот сайт, вы соглашаетесь с использованием cookie-файлов.
Принять
Отказаться
Политика конфиденциальности