Модуль 13. Процессы. Работа с процессами

Введение

Этот модуль расскажет об особенностях жизненного цикла процессов в Linux, об их рождении, жизни и смерти. Вы узнаете, что такое сигналы, для чего они нужны и как их использовать. Будет рассмотрена работа планировщика задач CFS и способы приоритизации процессов в Linux. Мы также научимся продвинутым приемам извлечения информации о процессах и управления ими.

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

Основным назначением операционной системы, как мы знаем, является создание условий для работы прикладных приложений. Однако установленные в системе приложения — это всего лишь файлы, которые просто лежат на диске. Для того чтобы приложение «заработало», создается так называемый процесс.

При запуске программы операционная система выделяет экземпляру приложения независимое адресное пространство памяти, назначает уникальный идентификатор (Process Identifier, PID) и вносит запись в таблицу процессов. С этого момента планировщик задач (scheduler) начинает выделять процессу кванты процессорного времени, и программа оживает.

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

Процессы в Linux и Windows

Дерево процессов в Linux

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

Для просмотра таблицы процессов в CMD мы использовали команду tasklist, в PowerShell командлет Get-Process, а в Linux для этого предназначена утилита ps. И начнем мы с наиболее часто используемых ключей aux:

localadmin@astra:~$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY   STAT START  TIME COMMAND
root         1  0.0  0.2 103172 11500 ?     Ss   05:56  0:00 /sbin/init
root         2  0.0  0.0      0     0 ?     S    05:56  0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?     I<   05:56  0:00 [rcu_gp]
...

Назначение использованных нами ключей следующее:

  • a — отобразить процессы всех пользователей;

  • u — показать, кто является владельцем процесса;

  • x — показать процессы, у которых нет управляющего терминала, например, службы.

Внимание

Для обеспечения обратной совместимости Bash-скриптов утилита ps поддерживает ключи, используемые разными операционными системами: BSD (без дефисов), POSIX (c дефисами) и GNU (c двумя дефисами и длинными ключами). Поэтому короткие ключи, совпадая по написанию, могут иметь совершенно разный смысл, например, команды ps -a и ps a покажут совсем не одно и то же.

Еще интереснее пример с командой ps -aux, когда перед группой ключей ставится символ дефиса. По правилам POSIX эта команда должна вывести все процессы для пользователя с именем «x», но т.к. такого пользователя не существует в системе, утилита понимает, что мы имели в виду «aux» без дефиса, и показывает нам этот результат.

Давайте с помощью ключей -ef выведем ту же информацию, но с идентификатором родителя и поговорим об иерархии процессов в Linux:

localadmin@astra:~$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 09:41 ?        00:00:01 /sbin/init
root         2     0  0 09:41 ?        00:00:00 [kthreadd]
root         3     2  0 09:41 ?        00:00:00 [rcu_gp]
root         4     2  0 09:41 ?        00:00:00 [rcu_par_gp]
root         5     2  0 09:41 ?        00:00:00 [slub_flushwq]
root         6     2  0 09:41 ?        00:00:00 [netns]
root         8     2  0 09:41 ?        00:00:00 [kworker/0:0H-events_highpri]
...

Назначение использованных нами ключей следующее:

  • Ключ -e — отобразить процессы всех пользователей (то же самое, что ключ -a);

  • Ключ -f — вывести больше доступной информации, например, идентификатор родителя.

localadmin@astra:~$ ps aux
UID        PID  PPID  C STIME TTY        TIME  CMD
root       1       0  0 20:03 ?      00:00:00  /sbin/init
root       2       0  0 20:03 ?      00:00:00  [kthreadd]
root       3       2  0 20:03 ?      00:00:00  [rcu_gp]
...

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

В системе Linux, напротив, установлена жесткая иерархия, поэтому описанная выше ситуация невозможна. Иерархический подход позволяет при закрытии терминала отправить всем дочерним процессам сигнал SIGHUP, чтобы закрыть их автоматически. Если же процесс был запущен через команду nohup и нужно, чтобы он продолжил свою работу, то он станет «осиротевшим» и будет автоматически усыновлен процессом init (systemd) с PID=1.

Проведем эксперимент, который наглядно покажет разницу в поведении систем:

  • Если запустить приложение calc.exe из терминала cmd или PowerShell, то после закрытия терминала калькулятор продолжит работу как ни в чем ни бывало, что является вполне ожидаемым поведением.

  • Если же мы из терминала Gnome Terminator запустим калькулятор в фоновом режиме командой kcalc & и закроем окно терминала c помощью ALT + F4, а не через команду exit, то терминал закроется вместе с калькулятором. А это уже ни разу не ожидаемое поведение.

  • А теперь повторим то же самое в fly-term от Astra Linux и увидим, что терминал можно закрывать хоть крестиком, хоть через exit, а калькулятор остается на месте, как будто его запустили через nohup, что намного привычнее для Windows-администраторов. Ой, ну, что вы…что вы… даже не благодарите.

Используя значение PPID, мы можем легко найти все процессы, запущенные из текущей оболочки. При этом мы, конечно, можем поупражняться в составлении трехэтажных регулярных выражений, но проще будет воспользоваться специальной утилитой pgrep и системной переменной $$, в которой содержится идентификатор текущего процесса. Команда в этом случае будет выглядеть так:

localadmin@astra:~$ ps -f -p$(pgrep --parent=$$)
UID        PID  PPID  C STIME TTY     STAT   TIME  CMD
localad+  2322  1395  0 00:06 pts/0   Sl     0:00  kcalc
localad+  2328  1395  0 00:06 pts/0   Sl     0:00  kcalc
localad+  2334  1395  0 00:06 pts/0   Sl     0:00  kcalc

Возвращаясь к дереву процессов, обратим ваше внимание на то, что дерево, на самом деле, не одно, см. рис. 49. Чтобы убедиться в этом на практике, воспользуемся утилитой pstree и выведем список всех потомков процесса с PID=0, которые были порождены ядром системы:

localadmin@astra:~$ pstree -p 0
?()─┬─kthreadd(2)─┬─acpi_thermal_pm(96)
    │             ├─ata_sff(84)
    │             ├─audit_prune_tre(367)
    │             ├─blkcg_punt_bio(82)
...
    │             ├─writeback(30)
    │             └─zswap-shrink(125)
    └─systemd(1)─┬─NetworkManager(474)─┬─{NetworkManager}(502)
                 │                     └─{NetworkManager}(503)
                 ├─VBoxClient(1232)───VBoxClient(1233)─┬─{VBoxClient}(1235)
                 │                                     └─{VBoxClient}(1236)
                 ├─VBoxClient(1244)───VBoxClient(1245)─┬─{VBoxClient}(1247)
                 │                                     └─{VBoxClient}(1248)
                 ├─VBoxClient(1251)───VBoxClient(1253)─┬─{VBoxClient}(1255)
                 │                                     ├─{VBoxClient}(1256)
                 │                                     └─{VBoxClient}(1257)
...

Процесс systemd или /sbin/init является процессом подсистемы инициализации и управления службами systemd, которая пришла на замену устаревшей подсистеме init. Новая реализация обеспечила распараллеливание запуска служб, что позволило существенно ускорить загрузку ОС. В настоящий момент systemd полностью вытеснила init SysV, но файл /sbin/init используется до сих пор и является символьной ссылкой на /lib/systemd/systemd.

Процесс [kthreadd] является диспетчером потоков, а квадратные скобки указывают нам на то, что это процесс самого ядра ОС. Второе дерево потребовалось, потому что для управления потоками нельзя было использовать процесс systemd, который работает в пользовательском пространстве.

../_images/alse_mod13_linux_process_trees.png

рис. 49 Деревья процессов в Linux

Адресное пространство

Как уже было сказано ранее, каждому процессу выделяется независимое адресное пространство памяти. Максимальный размер пространства в 64-битных системах в теории может доходить до 264B, а на практике для x86 процессоров не превышает 248B, т.е. до 256 ТБ (см. вывод команды cat /proc/cpuinfo «address sizes … 48 bits virtual»). Но это все равно чуть больше, чем дохарда. Хотя, кто его знает… Биллу Гейтсу до сих пор припоминают его «640 КБ должно хватить всем».

Важно понимать, что размер адресного пространства и объем памяти, потребляемый процессом, — это две большие разницы. Все адресное пространство разбивается на страницы объемом в 4Кб (см. getconf PAGE_SIZE), которых у процесса может быть, как у дурака фантиков. Однако большая часть этих страниц остается пустой, то есть не сопоставлена с реальной памятью компьютера, см. рис. 50:, поэтому процесс занимает ровно столько памяти, сколько он запросил, или как еще говорят «аллоцировал» (от англ. allocation – резервировать).

../_images/alse_mod13_address_space.png

рис. 50 Отображение страниц адресного пространства приложений на ОЗУ и файл подкачки

Обычно процессы могут аллоцировать весь доступный объем памяти, и ничего настраивать дополнительно не требуется. Выполните команду ulimit -a, и вы увидите, что для «virtual memory» установлено значение «unlimited»:

localadmin@astra:~$ ulimit -a
core file size         (blocks, -c) 0
data seg size          (kbytes, -d) unlimited
scheduling priority            (-e) 0
file size              (blocks, -f) unlimited
pending signals                (-i) 15317
max locked memory      (kbytes, -l) 65536
max memory size        (kbytes, -m) unlimited
open files                     (-n) 1024
pipe size           (512 bytes, -p) 8
POSIX message queues    (bytes, -q) 819200
real-time priority             (-r) 0
stack size             (kbytes, -s) 8192
cpu time              (seconds, -t) unlimited
max user processes             (-u) 15317
virtual memory         (kbytes, -v) unlimited
file locks                     (-x) unlimited

Однако бывают ситуации, когда мы сталкиваемся, например, с утечкой памяти, и, чтобы дожить до патча, устраняющего проблему, приходится подкручивать настройки. Например, с помощью команды ulimit -v 512000 мы можем ограничить потребление памяти процессами «на лету», а с помощью строки «* - as 512000» в конфигурационном файле /etc/security/limits.conf выставить эти ограничения на постоянной основе.

Добавим еще, что из соображений безопасности адресные пространства процессов независимы друг от друга, поэтому один процесс не может напрямую получить доступ к переменным и структурам данных другого процесса. В тех случаях, когда это действительно требуется, процессы должны обмениваться информацией через механизмы межпроцессного взаимодействия (от англ. Inter-Process Communication, IPC).

Как вы помните, в Linux основными механизмами IPC являются файлы, каналы (pipe, fifo), сокеты (Unix и TCP/IP), сигналы, разделяемая память и др. В Windows есть аналогичные технологии каналов, TCP/IP сокетов, разделяемой памяти, но при организации межпроцессного взаимодействия в большей степени используются программные интерфейсы, такие как объектная модель компонентов (от англ. Component Object Model, COM) или удаленный вызов процедур (от англ. Remote Procedure Call, RPC). В том числе по этой причине Linux работает пошустрее.

Порождение процесса

В системе Linux новый процесс создается вызовом ядра fork(), во время выполнения которого происходит полное копирование адресного пространства родительского процесса, назначается собственный PID/PPID и обнуляется статистика выполнения в таблицах ОС. В ряде случаев этого бывает достаточно, но если требуется запустить другой программный код (например, выполнить ps из командной строки bash), то сразу после fork() следует еще один системный вызов execve(), см. рис. 51.

Существует целое семейство вызовов exeс* (см. справку man 3 exec), которые отличаются набором параметров и логикой работы. Например, вызов execl() имеет дело со списком, а execv() c вектором. Но все они решают одну и ту же задачу, просто немного по-разному.

../_images/alse_mod13_process_branching.png

рис. 51 Схема ветвления процессов

Важно понимать, что копирование процесса происходит чрезвычайно быстро, так как копируются не сами данные, а только список страниц памяти, где эти данные хранятся. На все эти страницы устанавливается отметка Copy-on-Write (COW), поэтому, как только одному из процессов требуется внести изменения, для него создается копия соответствующей страницы. В итоге fork() оказывается значительно быстрее, чем функция CreateProcess() из Win32 API, хотя на современных процессорах это уже не столь важно.

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

Завершение процесса

Процесс может завершить свою работу штатно, когда программный код полностью выполнил поставленную перед ним задачу, из-за непредвиденной ошибки или аварийно по требованию администратора, например, командой kill -9 $(pidof kcalc).

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

Проблема с неупокоенными процессами заключается в том, что количество идентификаторов PID в дистрибутивах Linux всегда ограничено. К примеру, в Astra Linux их по умолчанию может быть не больше 32 768 (см. вывод команды cat /proc/sys/kernel/pid_max). Поэтому, когда такие зомби восстают регулярно и в большом количестве, наступает зомби-апокалипсис, и система перестает запускать новые процессы.

Зомби-процессы могут появляться как по причине зависания родительского процесса, так и в связи с ошибками в программном коде, но отправлять SIGKILL зомби-процессам совершенно бесполезно, ибо то, что мертво, умереть не может. Чтобы очистить систему от зомби, можно еще раз вручную направить сигнал SIGCHLD родительскому процессу с помощью команды kill -s SIGCHLD <PPID>. Если же родительский процесс завис и по-прежнему отказывается хоронить зомби, следующим шагом будет удаление родительского процесса. И не забываем про «семь бед – один reset» — после перезагрузки ни один зомби точно не выживет.

Состояния процесса во время его существования

Жизненный цикл процесса предусматривает 5 основных состояний, см. рис. 52. Посмотреть текущее состояние можно с помощью команды ps aux в колонке STAT:

  • R - готов (ready) или выполняется (running).

  • D - непрерываемое ожидание (uninterruptible sleep) - ожидание определенного события, чаще всего ожидания операции ввода-вывода.

  • S - прерываемое ожидание (interruptible sleep) - ожидание неопределенного события или сигнала.

  • T - остановка - процесс приостановлен, например, отладчиком.

  • Z - зомби (zombie) - завершен, но сигнал SIGCHLD не получен родителем.

../_images/alse_mod13_process_lifecycle.png

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

Статусы готов и выполняется обозначаются одной буквой R, т.к. процесс получает кванты процессорного времени по сто раз в секунду, и эта информация не несет для пользователя никакой полезной информации.

Если процессу требуется доступ к устройству ввода-вывода (например, прочитать данные из файла), то без получения этих данных дальнейшее выполнение процесса будет невозможным, и процесс перейдет в состояние непрерываемого ожидания (D). Это ожидание называется непрерываемым, так как даже команда kill -9 pid в таком состоянии не более, чем предложение «свернуть удочки», которое процесс может полностью проигнорировать.

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

Отправкой сигнала SIGSTOP процесс может быть переведен в состояние остановлен (T), в котором он замирает до получения сигнала разморозки SIGCONT. Вы можете использовать это состояние для приостановки процесса, который начал потреблять слишком много ресурсов, чтобы спокойно проанализировать причины, не завершая работу приложения сигналом SIGKILL.

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

Потоки в Linux

Кроме вызова fork() существует также системный вызов clone(), который позволяет создавать процессы с разделяемым адресным пространством или так называемые потоки (англ. thread).

Потоки позволяют организовать параллельную обработку данных на нескольких ядрах вычислительного узла, что сильно повышает итоговую скорость выполнения задачи. Например, если у вас 4 ядра плюс гипертрейдинг, то вы можете архивировать данные в 8 потоков, что будет в 8 раз быстрее.

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

  • CLONE_VM — общее адресное пространство (любой из потоков может поменять страницы в памяти, и эти изменения будут видны всем потокам);

  • CLONE_FS — общие сведения о файловой системе (корневой и текущий каталоги, umask, права на создаваемые файлы и каталоги по умолчанию);

  • CLONE_FILES — общая таблица открытых файлов;

  • CLONE_SIGHAND — общая таблица обработчиков сигналов;

  • CLONE_PARENT — позволяет создавать сестринские процессы с тем же PPID, как у себя.

С точки зрения Linux управление процессами и потоками – это очень похожие задачи, поэтому и для работы с ними используются одни и те же инструменты. Например, команда ps -T -p <pid> покажет вам все потоки указанного процесса.

Сигналы для процессов в Linux

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

Для отправки сигналов из командной строки предназначена утилита kill (от англ. убить). Название утилиты объясняется тем, что без дополнительных уточнений она отправляет сигнал SIGTERM, который как раз и означает завершение работы. Для того чтобы отправить какой-то другой сигнал, нужно указать цифровой код сигнала -<signal> или его имя с помощью ключа -s (--signal):

Запускаем калькулятор в фоновом режиме:

localadmin@astra:~$ kcalc &
[1] 5403

Завершаем процесс с выбранным PID 5403 из прошлой команды:

localadmin@astra:~$ kill -SIGTERM 5403
localadmin@astra:~$

Альтернативные варианты написания команды:

  • kill –TERM 5403

  • kill -15 5403

  • kill 5403

Процессы Linux поддерживают 64 сигнала, список которых можно посмотреть с помощью ключа -L (-l, --list) команды kill:

localadmin@astra:~$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 2) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
1)  SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
2)  SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
3)  SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
4)  SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
5)  SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
6)  SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
7)  SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
8)  SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
9)  SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
10) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
11) SIGRTMAX-1  64) SIGRTMAX

Чаще всего администраторы используют в работе сигналы:

  • Сигнал SIGINT(2) предназначен для прерывания работы приложений по требованию пользователя (от англ. interrupt — прервать) и отправляется автоматически активному процессу терминала по нажатию клавиш Ctrl + C.

    Чаще всего администраторы отправляют этот сигнал приложениям через горячие клавиши, но можно сделать это и через утилиту kill. Продвинутые приложения могут реализовывать более сложную логику обработки этого сигнала, чем просто прерывание работы.

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

  • Сигнал SIGKILL(9) требует процесс немедленно завершить свою работу. Процесс не имеет права проигнорировать этот сигнал и не может переопределить его обработчик, поэтому, если процесс не завершился по сигналу -9, то это указывает на какие-то проблемы в работе операционной системы. По своей сути сигнал SIGKILL похож на команду End task диспетчера задач Windows.

  • Сигнал SIGTERM(15) отправляется процессу по умолчанию, если команде kill передать только идентификатор процесса. Сигнал просит процесс приступить к штатному завершению работы (от англ. software termination — завершение работы программного обеспечения).

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

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

Продвинутые администраторы расширяют набор своих инструментов сигналами:

  • Сигнал SIGHUP(1) посылается всем дочерним процессам терминала при его закрытии, чтобы они тоже завершили свою работу (от англ. hang up — повесить трубку). Название сигнала берет свое начало со времен аппаратных терминалов и телефонных линий связи.

    Для того чтобы приложение игнорировало сигнал -1, его можно запустить с помощью команды nohup. Если закрыть терминал, такие процессы «осиротеют» и будут удочерены процессом init (systemd).

localadmin@astra:~$ kcalc &
[3] 20613

Приложение завершает свою работу:

localadmin@astra:~$ kill -SIGHUP 20613
localadmin@astra:~$ nohup kcalc &

Запускаем команду через nohup:

localadmin@astra:~$ nohup kcalc &
[4] 20991
[3] Обрыв терминальной линии kcalc

Завершить процесс с помощью сигнала HUP больше не удается, он игнорируется приложением:

localadmin@astra:~$ kill -SIGHUP 20991
localadmin@astra:~$
  • Сигнал SIGCHLD(17) направляется родителю при завершении дочернего процесса. При появлении зомби-процессов сигнал может быть направлен вручную для обработки очереди.

  • Сигнал SIGSTOP(19) переводит процесс в состояние «остановлен», что удобно для отладки проблем с высоким потреблением ресурсов, когда требуется вернуть систему к жизни, не завершая проблемный процесс полностью. Процесс не имеет права проигнорировать этот сигнал и не может переопределить его обработчик. Для возобновления работы процесса предназначен сигнал SIGCONT.

  • Сигнал SIGTSTP(20) предназначен для остановки работы приложений из терминала (от англ. TTY stop) и отправляется автоматически активному процессу терминала по нажатию клавиш Ctrl + Z.

  • Сигнал SIGCONT(18) возобновляет работу процесса, который был остановлен с помощью сигналов SIGSTOP и SIGTSTP.

Каждый сигнал является указателем на область памяти, где находится обработчик, и многие из этих обработчиков могут быть переопределены внутри приложения через функцию trap(). Например, служба SSSD, обеспечивающая работу компьютера в домене, принимает сигналы SIGUSR2 и SIGUSR1 для того, чтобы переключиться в режим онлайн/офлайн соответственно:

admin@dc-1:~$ sudo kill -SIGUSR1 "$(pidof sssd)"
admin@dc-1:~$ sudo sssctl domain-status ald.company.lan
Online status: Offline

Active servers:
IPA: dc-1.ald.company.lan

Discovered IPA servers:
- dc-1.ald.company.lan

admin@dc-1:~$ sudo kill -SIGUSR2 "$(pidof sssd)"
admin@dc-1:~$ sudo sssctl domain-status ald.company.lan
Online status: Online

Active servers:
IPA: dc-1.ald.company.lan

Discovered IPA servers:
- dc-1.ald.company.lan

Планировщик задач в Linux и управление приоритетами процессов

Планировщик задач

Планировщик задач – это часть ядра ОС, необходимая для распределения ресурсов процессора между процессами. Планировщик преследует несколько целей:

  • Максимизировать пропускную способность, то есть количество задач, выполняемых за единицу времени.

  • Минимизировать время ожидания, то есть время, прошедшее с момента готовности процесса до начала его выполнения.

  • Минимизировать время ответа, то есть время, прошедшее с момента готовности процесса до завершения его выполнения.

  • Максимизировать равнодоступность, то есть справедливое распределение ресурсов между задачами.

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

Группы процессов

В Linux существуют три основные группы процессов: First In, First Out (FIFO), Round Robin (RR) и Other. Первые две представляют собой процессы реального времени, которые должны выполняться немедленно, без задержек, а последняя, Other - условные процессы, при выполнении которых задержки не являются критичными для работы системы.

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

../_images/alse_mod13_process_logic.png

рис. 53 Логика выбора алгоритма и политики планирования процессов

FIFO процессы (first in, first out, первый вошел, первый вышел) имеют самый высокий приоритет из всех. Такой процесс фактически работает в однопрограммном режиме и не реагирует ни на какие сигналы. Использование таких процессов несет серьезные риски, так как ошибка в его выполнении может критически повлиять на всю систему в целом.

В Linux используется всего несколько FIFO потоков ядра, для выполнения которых критически важно, чтобы их операции не прерывались и завершались без сбоев, например, изменение статуса процесса диспетчером процессов. В противном случае мы могли бы получить некорректную таблицу состояний процессов.

Процессы Round Robin (по круговой схеме) имеют более низкий приоритет по сравнению с FIFO процессами, поэтому при активизации FIFO процесса будут им вытеснены. Процессы RR равны между собой по приоритету в пределах одной очереди. Пока существует несколько процессов Round Robin. Каждому из них диспетчер выделяет определенный квант времени, и они будут выполняться по кругу, пока все такие процессы не будут завершены или не перейдут в состояния ожидания или остановки.

Процессы Other (все остальные) имеют самый низкий приоритет, то есть могут выполняться, только если нет активных FIFO или Round Robin процессов. В современных дистрибутивах Linux этими процессами занимается планировщик CFS (Completely Fair Scheduler, абсолютно справедливый планировщик), который старается соблюдать принцип справедливости, чтобы каждый процесс получил одинаковое количество процессорного времени. Кванты времени вычисляются так, чтобы исключить слишком частые переключения между процессами.

Отличительной особенностью планировщика CFS является высокая скорость сортировки процессов по потреблению ими процессорного времени за время log(N), так как для сортировки используется красно-черное дерево. Благодаря этому удалось добиться действительно справедливого распределения процессорного времени между процессами при высокой скорости самого планирования.

Политики планирования

Группы процессов FIFO, RR и Other соответствуют политикам планирования SCHED_FIFO, SCHED_RR и SCHED_OTHER (всего таких политик 6). Посмотреть список политик планирования можно командой chrt -m.

localadmin@astra:~$ chrt -m
SCHED_OTHER min/max priority    : 0/0
SCHED_FIFO min/max priority     : 1/99
SCHED_RR min/max priority       : 1/99
SCHED_BATCH min/max priority    : 0/0
SCHED_IDLE min/max priority     : 0/0
SCHED_DEADLINE min/max priority : 0/0

Как видим, выбор приоритета (а именно приоритета реального времени) доступен только в политиках SCHED_FIFO и SCHED_RR - от 1 до 99, для остальных политик он всегда 0.

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

Каждому процессу присваивается приоритет. Это целое число от 39 до -100, где 39 - наименьший приоритет, а -100 - наивысший. Процессы с приоритетами от 39 до 0 - это обычные процессы из группы Other. Их приоритет не может быть меньше 0. По умолчанию все процессы из политики Other имеют приоритет 20, однако это значение может быть скорректировано как при запуске процесса (команда nice), так и во время его работы (команда renice). Эти команды меняют параметр NICE процессов - его «вежливость» (от англ. niceness), которая по умолчанию равна 0.

../_images/alse_mod13_correlation.png

рис. 54 Соотношение параметров приоритета процесса, его «вежливости» и приоритета реального времени

Параметр NICE может принимать значение от +19 до -20. При этом значение приоритета по умолчанию (20) суммируется со значением NICE, и, как упоминалось ранее, итоговый результат может принимать значение от 39 до 0.

Процессы с приоритетом от -1 до -100 - это процессы реального времени. У таких процессов кроме обычного приоритета существует приоритет реального времени, который используется в политиках планирования FIFO и RR. Для преобразования приоритета реального времени (rt_prior) в обычный приоритет процесса необходимо из -1 вычесть rt_prior. Например, при rt_prior равному 50, обычный приоритет будет равен -51 (-1 - 50 = -51).

Узнать текущее значение приоритета и параметра NICE можно в выводе команды htop - колонки PRI и NI.

Задания, интерактивный и фоновый режимы работы процесса

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

Остановка процессов. Когда мы запускаем утилиты как обычно, например, kcalc, они работают в интерактивном режиме, поэтому блокируют работу с терминалом. Если нам нужно вернуться к работе в терминале, мы можем закрыть приложение полностью клавишами Ctrl + C или временно приостановить его работу сочетанием Ctrl + Z. При этом калькулятор останется на экране, но перестанет реагировать на наши действия.

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

Команда fg <задание> переводит указанное задание в интерактивный режим (от англ. foreground — передний план). Задание может быть указано следующим образом:

  • <N> — порядковый номер задания, см. команду jobs далее.

  • %шаблон — поиск задания по его имени, например, %ping или %nmap.

  • %+ и %- — следующая и предыдущая задача.

  • %% — последняя задача. То же самое, что не указывать номер задания.

Перевод процесса в фоновый режим. Если же мы хотим продолжить работу с калькулятором, но не хотим терять доступ к терминалу, мы можем перевести приложение не в интерактивный, а в фоновый режим командой bg. В этом случае нам будут доступны и калькулятор, и терминал одновременно, как будто калькулятор изначально был запущен командой kcalc & с амперсандом на конце.

Команда bg <задание> переводит указанное задание в фоновый режим (от англ. background — задний план). Задание задается таким же образом, как в команде fg, поэтому не будем повторяться.

Просмотр фоновых заданий выполняется командой jobs. У этой команды есть следующие ключи:

  • Ключ -l – выводит список процессов заданий с PID процесса и информацией по умолчанию.

  • Ключ -n – выводит только те процессы, статус которых был изменен с последнего оповещения.

  • Ключ -p – выводит список только PID фоновых процессов.

  • Ключ -r – выводит только запущенные фоновые процессы.

  • Ключ -s – выводит только остановленные фоновые процессы.

Давайте запустим три фоновых процесса и посмотрим список заданий:

localadmin@astra:~$ kcalc &
[1] 2514
localadmin@astra:~$ kcalc &
[2] 2523
localadmin@astra:~$ kcalc &
[3] 2531
localadmin@astra:~$ jobs
[1]   Запущен          kcalc &
[2]-  Запущен          kcalc &
[3]+  Запущен          kcalc &

Извлечение информации о процессах

Информация о процессах доступна через псевдофайловую систему /proc. Это универсальный интерфейс для доступа к данным о процессах и работе ядра ОС. Кроме того, используя определенные файлы, можно не только получать информацию о процессах, но и управлять некоторыми настройками ядра ОС. Утилиты для работы с процессами, такие как ps, top или htop, в качестве источника информации используют как раз эту псевдофайловую систему.

Для пользователя взаимодействие с файлами /proc выглядит как работа с обычными текстовыми файлами, но это совсем не так. Например, при чтении какого-либо файла командой cat происходит системный вызов, и система формирует текстовый ответ, который передается команде.

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

Вначале мы разберем, что хранится в каталогах /proc/PID/, где PID - числовой идентификатор процесса, например, /proc/1/, а затем посмотрим содержимое самого каталога /proc/.

Содержимое /proc/PID/

localadmin@astra:$ sudo ls /proc/1
arch_status         fd          numa_maps      smaps_rollup
attr                fdinfo      oom_adj        stack
autogroup           gid_map     oom_score      stat
auxv                io          oom_score_adj  statm
cgroup              limits      pagemap        status
clear_refs          loginuid    patch_state    syscall
cmdline             map_files   personality    task
comm                maps        projid_map     timens_offsets
coredump_filter     mem         root           timers
cpu_resctrl_groups  mountinfo   sched          timerslack_ns
cpuset              mounts      schedstat      uid_map
cwd                 mountstats  sessionid      wchan
environ             net         setgroups
exe                 ns          smaps

Файл /proc/cmdline – в нем содержится строка запуска процесса.

localadmin@astra:~$ cat /proc/1/cmdline && echo
/sbin/init

Файл /proc/exe – символическая ссылка, ведущая к полному пути до исполняемого файла. Полный путь необходим для однозначного понимания, какой именно файл был запущен.

localadmin@astra:~$ sudo ls -l --color=always /proc/1/exe
lrwxrwxrwx 1 root root 0 июл 18 11:32 exe -> /usr/lib/systemd/systemd

Файл /proc/cwd – текущий рабочий каталог процесса PID1.

localadmin@astra:$ sudo ls -l --color=always /proc/1/cwd
lrwxrwxrwx 1 root root 0 июл 27 13:06 cwd -> /

Файл /proc/environ – окружение процесса, создающее контекст его выполнения.

localadmin@astra:~$ sudo cat /proc/1/environ && echo
SHLVL=1HOME=/init=/sbin/initTERM=linuxBOOT_IMAGE=/boot/vmlinuz-5.15.0-33-genericdrop_caps=PATH=/sbin:/usr/sbin:/bin:/usr/binPWD=/rootmnt=/root

Каталог /proc/fd/ – дескрипторы открытых файлов (от англ. file descriptors). Каждый файл в fd/ представляет собой символическую ссылку и имеет числовое имя. Это не номер айноды в файловой системе, это уникальный номер в пределах процесса, который позволяет процессу обращаться к конкретным файлам, с которыми он работает. Дескрипторы 0, 1 и 2 - это стандартные ввод, вывод и вывод ошибок.

localadmin@astra:~$ sudo ls -l /proc/1/fd --color=always
итого 0
lrwx------ 1 root root 64 июл 18 11:32 0 -> /dev/null
lrwx------ 1 root root 64 июл 18 11:32 1 -> /dev/null
...
lrwx------ 1 root root 64 авг  4 09:03 109 -> 'socket:[20856]'
lr-x------ 1 root root 64 авг  4 09:03 11 -> anon_inode:inotify
...
lr-x------ 1 root root 64 авг  4 09:03 119 -> 'pipe:[16902]'
lr-x------ 1 root root 64 июл 18 11:32 12 -> /dev/autofs
lrwx------ 1 root root 64 авг  4 09:03 120 -> 'socket:[16920]'
lrwx------ 1 root root 64 авг  4 09:03 121 -> /run/initctl
lrwx------ 1 root root 64 авг  4 09:03 122 -> 'socket:[16904]'
lrwx------ 1 root root 64 авг  4 09:03 123 -> 'socket:[16906]'
lr-x------ 1 root root 64 авг  4 09:03 13 -> /proc/1/mountinfo
lr-x------ 1 root root 64 авг  4 09:03 14 -> anon_inode:inotify
lr-x------ 1 root root 64 авг  4 09:03 15 -> /proc/swaps
...
lrwx------ 1 root root 64 июл 18 11:32 2 -> /dev/null
lrwx------ 1 root root 64 июл 18 11:32 20 -> 'socket:[27113]'
...

Файл /proc/io – содержит сведения об объемах данных, прочитанных и записанных процессом в хранилище информации.

localadmin@astra:~$ sudo cat /proc/1/io
rchar: 11296824165
wchar: 159986595
syscr: 6481108
syscw: 467703
read_bytes: 801298432
write_bytes: 258985984
cancelled_write_bytes: 43184128

Файл /proc/limits – отображает различные ограничения процесса, установленные конфигурационным файлом /etc/security/limits.conf и командой ulimit.

localadmin@astra:~$ sudo cat /proc/1/limits
Limit                     Soft Limit           Hard Limit          Units
Max cpu time              unlimited            unlimited           seconds
Max file size             unlimited            unlimited           bytes
Max data size             unlimited            unlimited           bytes
Max stack size            8388608              unlimited           bytes
Max core file size        0                    unlimited           bytes
Max resident set          unlimited            unlimited           bytes
Max processes             7523                 7523                processes
Max open files            1048576              1048576             files
Max locked memory         67108864             67108864            bytes
Max address space         unlimited            unlimited           bytes
Max file locks            unlimited            unlimited           locks
Max pending signals       7523                 7523                signals
Max msgqueue size         819200               819200              bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited           us

Файл /proc/maps – физические адреса страниц памяти, используемые в данный момент.

localadmin@astra:~$ sudo cat /proc/1/maps |  head
5e9ee4066000-5e9ee4094000 r--p 00000000 08:01 657629                   /usr/lib/systemd/systemd
5e9ee4094000-5e9ee41af000 r-xp 0002e000 08:01 657629                   /usr/lib/systemd/systemd
5e9ee41af000-5e9ee4204000 r--p 00149000 08:01 657629                   /usr/lib/systemd/system
...

Файл /proc/pagemap для каждой виртуальной страницы определяет её фактическое положение: в физической памяти или в файле подкачки. Информация хранится в двоичном коде.

Файл /proc/sched –отображение текущих значений переменных планировщика процессов, необходимых для корректной работы планировщика SFC.

localadmin@astra:~$ sudo cat /proc/1/sched
systemd (1, #threads: 1)
se.exec_start                                :    1290085360.092074
se.vruntime                                  :         11829.729715
se.sum_exec_runtime                          :         21150.129581
se.nr_migrations                             :                 2199
nr_switches                                  :                39002
nr_voluntary_switches                        :                29552
nr_involuntary_switches                      :                 9450
se.load.weight                               :              1048576
se.avg.load_sum                              :                  285
se.avg.runnable_sum                          :               291840
se.avg.util_sum                              :               271360
se.avg.load_avg                              :                    0
se.avg.runnable_avg                          :                    0
se.avg.util_avg                              :                    0
se.avg.last_update_time                      :     1290085360091136
se.avg.util_est.ewma                         :                    7
se.avg.util_est.enqueued                     :                    0
uclamp.min                                   :                    0
uclamp.max                                   :                 1024
effective uclamp.min                         :                    0
effective uclamp.max                         :                 1024
policy                                       :                    0
prio                                         :                  120
clock-delta                                  :                   95
mm->numa_scan_seq                            :                    0
numa_pages_migrated                          :                    0
numa_preferred_nid                           :                   -1
total_numa_faults                            :                    0
current_node=0, numa_group_id=0
numa_faults node=0 task_private=0 task_shared=0 group_private=0 group_shared=0

Файлы /proc/stat и /proc/status – близкие по своей сути, отражают основные сведения о процессе. Файл stat - машиночитаемый формат, а status - человекочитаемый. Большинство параметров, выводимых утилитой ps, она получает из структур данных, аналогичных тем, которые отображаются в этих файлах.

localadmin@astra:~$ sudo cat /proc/1/stat
1 (systemd) S 0 1 1 0 -1 4194560 111979 3580285 170 48914 1384 733 32339 27124 20 0 1 0 11
1056563202873 18446744073709551615 104036523655168 104036524814201 140723869122320 0 0 0
671173123 4096 12601 0 0 17 0 0 0 0 0 0 104036525166288 104036525396288 104036533329920
140723869130571 140723869130582 140723869130582 140723869130733 0
localadmin@astra:/proc/1$ sudo cat status
Name:   systemd
Umask:  0000
State:  S (sleeping)
Tgid:   1
Ngid:   0
Pid:    1
PPid:   0
TracerPid:      0
Uid:    0       0       0       0
Gid:    0       0       0       0
FDSize: 128
Groups:
NStgid: 1
NSpid:  1
NSpgid: 1
NSsid:  1
VmPeak:   168716 kB
VmSize:   103180 kB
...
Mems_allowed_list:      0
voluntary_ctxt_switches:        29574
nonvoluntary_ctxt_switches:     9459

Файл statm - статистика по использованию памяти. Это 7 чисел, из которых только 5 имеют значения в современных версиях ядра. Все значения - количество страниц памяти:

  • 1 – общий размер памяти, занимаемой программой (то же, что и VmSize в файле status)

  • 2 – размер резидентной памяти (то же, что и VmRSS в файле status)

  • 3 – разделяемые страницы памяти (то же, что и RssFile+RssShmem в файле status)

  • 4 – размер сегмента, отведенного под код

  • 5 – не используется (всегда 0, начиная с ядра 2.6)

  • 6 – размер сегмента данных и стека

  • 7 – не используется (всегда 0, начиная с ядра 2.6)

localadmin@astra:~$ cat /proc/1/statm
25795 2873 2179 283 0 4927 0

Содержимое /proc

Ниже представлено содержимое каталога /proc/. В выводе команды все каталоги с PID заменены на {PID 1,2,…,N} для лучшего восприятия. Файлы, хранящиеся в корне каталога /proc/, характеризуют состояние и характеристики всего вычислительного узла и ядра ОС.

localadmin@astra:~$ ls /proc
{PID 1,2, … N}
asound         irq          schedstat      bootconfig     kallsyms     scsi
buddyinfo      kcore        self           bus            keys         slabinfo
cgroups        key-users    softirqs       cmdline        kmsg         stat
consoles       kpagecgroup  swaps          cpuinfo        kpagecount   sys
crypto         kpageflags   sysrq-trigger  devices        loadavg      sysvipc
diskstats      locks        thread-self    dma            mdstat       timer_list
driver         meminfo      tty            dynamic_debug  misc         uptime
execdomains    modules      version        fb             mounts       version_signature
filesystems    mtrr         vmallocinfo    fs             net          vmstat
interrupts     pagetypeinfo zoneinfo       iomem          partitions
ioports        pressure

Файл /proc/cmdline – список параметров, которые были переданы ядру при загрузке.

localadmin@astra:~$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-5.15.0-33-generic root=UUID=1864fbac-4e75-42ec-9a52-c0944d4fd6b9 ro parsec.mac=0 quiet net.ifnames=0

Файл /proc/cpuinfo – сведения о всех установленных процессорах.

localadmin@astra:~$ cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 79
model name      : Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz
stepping        : 1
cpu MHz         : 2394.456
cache size      : 35840 KB
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 2
...

Файл /proc/diskstats – статистика операций со всеми дисками. Для каждого диска своя строка. Описание полей доступно по ссылке.

localadmin@astra:~$ cat /proc/diskstats
 7   0 loop0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 . . .
 8   1 sda1 44186 11778 2356130 13854 240755 305673 4556040 132537 0 336236 146391 0 0 0 0 0 0
 8   2 sda2 2 0 4 0 0 0 0 0 0 8 0 0 0 0 0 0 0
 8   5 sda5 69 0 5000 22 0 0 0 0 0 68 22 0 0 0 0 0 0
11   0 sr0 33 0 160 11 0 0 0 0 0 44 11 0 0 0 0 0 0

Файл /proc/meminfo – отображение информации о состоянии памяти. Предоставляет больше параметров, чем утилита free.

localadmin@astra:~$ free
              total        used        free      shared  buff/cache   available
Mem:        4007624      448304     1761592       27816     1797728     3284820
Swap:        998396           0      998396

localadmin@astra:~$ cat /proc/meminfo
MemTotal:        2025208 kB
MemFree:           88064 kB
MemAvailable:    1295928 kB
Buffers:          181228 kB
Cached:          1101408 kB
SwapCached:            0 kB
Active:          1024936 kB
Inactive:         596484 kB
...

Файл /proc/devices – перечень устройств в системе.

localadmin@astra:~$ cat /proc/devices
Character devices:
  1 mem
  4 /dev/vc/0
  4 tty
  4 ttyS
  5 /dev/tty
...
Block devices:
  2 fd
  7 loop
  8 sd
  9 md
 11 sr
 65 sd
 66 sd
 67 sd
...

Файл /proc/filesystem – перечень файловых систем, поддерживаемых ядром ОС.

localadmin@astra:~$ cat /proc/filesystems
nodev   sysfs
nodev   tmpfs
nodev   bdev
nodev   proc
...
        ext3
        ext2
        ext4
...

Файл /proc/mounts – перечень смонтированных файловых систем (формат данных, аналогичен файлу /etc/fstab).

localadmin@astra:~$ cat /proc/mounts
sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
udev /dev devtmpfs rw,nosuid,relatime,size=963080k,nr_inodes=240770,mode=755,inode64 0 0
devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0
tmpfs /run tmpfs rw,nosuid,noexec,relatime,size=202524k,mode=755,inode64 0 0
/dev/sda1 / ext4 rw,relatime,errors=remount-ro 0 0
parsecfs /parsecfs parsecfs rw,sync,relatime 0 0
securityfs /sys/kernel/security securityfs
rw,nosuid,nodev,noexec,relatime 0 0
tmpfs /dev/shm tmpfs rw,nosuid,nodev,inode64 0 0

Файл /proc/modules – список подгруженных модулей ядра. Ядро Linux монолитное, но модульное, и мы можем управлять тем, какие модули подгружать, а какие нет, тем самым определяя функционал запускаемой ОС.

localadmin@astra:~$ cat /proc/modules
binfmt_misc 24576 1 - Live 0x0000000000000000 (E)
vboxvideo 36864 0 - Live 0x0000000000000000 (OE)
drm_ttm_helper 16384 1 vboxvideo, Live 0x0000000000000000 (E)
intel_rapl_msr 20480 0 - Live 0x0000000000000000 (E)
intel_rapl_common 32768 1 intel_rapl_msr, Live 0x0000000000000000 (E)

Файл /proc/swaps – список разделов подкачки.

localadmin@astra:~$ cat /proc/swaps
Filename             Type            Size        Used      Priority
/dev/sda5            partition       998396      0         -2

Файл /proc/version – версия ядра ОС.

localadmin@astra:~$ cat /proc/version
Linux version 5.15.0-33-generic (builder@build5) (gcc (AstraLinuxSE 8.3.0-6) 8.3.0, GNU ld (GNU Bin utils for AstraLinux) 2.31.1) #astra2+ci96 SMP Fri Oct 28 18:23:37 UTC 2

Каталог /sys/kernel/ содержит набор файлов, которые позволяют нам оперативно без перезагрузки изменять параметры ядра ОС (но таких параметров не очень много). Поэтому часть файлов в этом каталоге доступна для записи, и через эти интерфейсы мы можем управлять ядром. Некоторые из них будут рассмотрены в модуле, посвящённом ядру ОС.

localadmin@astra:~$ ls /proc/sys/kernel/
acct                 ngroups_max             sched_energy_aware
acpi_video_flags     nmi_watchdog            sched_rr_timeslice_ms
auto_msgmni          ns_last_pid             sched_rt_period_us
bootloader_type      numa_balancing          sched_rt_runtime_us
bootloader_version   oops_all_cpu_backtrace  sched_schedstats
bpf_stats_enabled    osrelease               sched_util_clamp_max
cad_pid              ostype                  sched_util_clamp_min
cap_last_cap         overflowgid             sched_util_clamp_min_rt_default
...

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

Для управления процессами в Linux существует набор утилит. Рассмотрим работу с основными из них: консольными утилитами (ps, top и htop, kill), а для графической (системный монитор).

Управление процессами через консольные утилиты

Просмотр процессов

Для просмотра процессов есть три основные консольные утилиты (ps, top и htop) и одна графическая (системный монитор). Утилита ps позволяет получить снимок текущего состояния всех или заданных процессов и их параметров.

localadmin@astra:~$ ps
PID TTY          TIME CMD
23526 pts/4    00:00:19 bash
32038 pts/4    00:00:00 ps
Просмотр процессов через утилиты top и htop

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

Основное отличие между ними в интерфейсе: htop более удобен для новичков и тех, кто работал с Windows Task Manager. Он поддерживает управление мышью и имеет более «дружелюбный» интерфейс управления.

../_images/alse_mod13_top_interface.png

рис. 55 Интерфейс утилиты top

../_images/alse_mod13_htop_interface.png

рис. 56 Интерфейс утилиты htop

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

../_images/alse_mod13_settings_menu.png

В меню Columns нам доступен выбор отображаемых столбцов и их описание.

../_images/alse_mod13_columns_menu.png

Через клавишу F1 нам доступна кратка справка. Полная справка доступна через man htop.

Утилита ps

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

  • -e – вывести на дисплей процессы всех пользователей. Не отображаются только процессы, не связанные с терминалом.

  • -a – вывести информацию обо всех процессах, за исключением лидеров сессий и процессов, не ассоциированных с терминалом.

  • -t – показывать только процессы из этого терминала.

  • -p – показывать информацию только об указанном процессе.

  • -u – вывод подробной информации в пользовательско-ориентированном формате.

  • -x – показать процессы без управляющего терминала.

  • -o – задать формат вывода информации.

Таким образом, команда ps aux выводит все активные процессы.

Для сортировки процессов можно воспользоваться параметром --sort, например, ps aux --sort=%mem или ps aux --sort=%cpu.

localadmin@astra:~$ ps aux --sort=%mem | tail -n 3
localad+  1866  0.0  1.7 565016 68348 ?        Ssl  12:30   0:00 nm-applet
localad+  1868  0.0  2.7 1524876 111060 ?      Ssl  12:30   0:00 fly-sound-applet
root       778  0.0  3.1 912424 125044 tty7    Ssl+ 09:41   0:08 /usr/lib/xorg/Xorg
...

Команда ps -eo euser,ruser,suser,fuser,f,comm,label выведет информацию об атрибутах EUID, RUID, SUID.

localadmin@astra:~$ ps -eo euser,ruser,suser,fuser,f,comm,label
EUSER    RUSER    SUSER    FUSER    F COMMAND         LABEL
root     root     root     root     4 systemd         0:0:0:0
root     root     root     root     1 kthreadd        0:0:0:0
...
localad+ localad+ localad+ localad+ 4 systemd         0:0:0:0
localad+ localad+ localad+ localad+ 5 (sd-pam)        0:0:0:0
localad+ localad+ localad+ localad+ 4 fly-wm          0:0:0:0
...

С помощью утилиты ps можно посмотреть и потоки. Воспользуйтесь командами ps -eLf и ps axms.

localadmin@astra:~$ ps -eLf
UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
root         1     0     1  0    1 фев22 ?     00:00:08 /sbin/init
. . .
localad+  1493  1411  1493  0    1 фев22 pts/2 00:00:00 /bin/bash
root     15418     1 15418  0   11 фев26 ?     00:00:29 /usr/sbin/syslog-ng -F --no-caps
root     15418     1 15430  0   11 фев26 ?     00:00:00 /usr/sbin/syslog-ng -F --no-caps
root     15418     1 15431  0   11 фев26 ?     00:00:00 /usr/sbin/syslog-ng -F --no-caps
root     15418     1 19949  0   11 00:01 ?        00:00:00 /usr/sbin/syslog-ng -F --no-caps
root     15418     1 19950  0   11 00:01 ?        00:00:00 /usr/sbin/syslog-ng -F --no-caps
root     15418     1 19951  0   11 00:01 ?        00:00:00 /usr/sbin/syslog-ng -F --no-caps
root     15418     1 19952  0   11 00:01 ?        00:00:00 /usr/sbin/syslog-ng -F --no-caps
root     15418     1 19953  0   11 00:01 ?        00:00:00 /usr/sbin/syslog-ng -F --no-caps
root     15418     1 19954  0   11 00:01 ?        00:00:00 /usr/sbin/syslog-ng -F --no-caps
root     15418     1 19955  0   11 00:01 ?        00:00:02 /usr/sbin/syslog-ng -F --no-caps
root     15418     1 19957  0   11 00:01 ?        00:00:06 /usr/sbin/syslog-ng -F --no-caps
localad+ 17557  1468 17557  0    1 фев26 pts/0 00:00:00 man sudoedit
localad+ 17568 17557 17568  0    1 фев26 pts/0 00:00:00 pager
...
localadmin@astra:~$ ps axmu
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.5 168924 11548 ?        -    фев22   0:08 /sbin/init
root         -  0.0    -      -     - -        Ss   фев22   0:08 -
. . .
localad+  1493  0.0  0.2   7856  4592 pts/2    -    фев22   0:00 /bin/bash
localad+     -  0.0    -      -     - -        Ss+  фев22   0:00 -
root         -  0.0    -      -     - -        Ssl  фев26   0:29 -
root         -  0.0    -      -     - -        Ssl  фев26   0:00 -
root         -  0.0    -      -     - -        Ssl  фев26   0:00 -
root         -  0.0    -      -     - -        Ssl  00:01   0:00 -
root         -  0.0    -      -     - -        Ssl  00:01   0:00 -
root         -  0.0    -      -     - -        Ssl  00:01   0:00 -
root         -  0.0    -      -     - -        Ssl  00:01   0:00 -
root         -  0.0    -      -     - -        Ssl  00:01   0:00 -
root         -  0.0    -      -     - -        Ssl  00:01   0:00 -
root         -  0.0    -      -     - -        Ssl  00:01   0:02 -
root         -  0.0    -      -     - -        Ssl  00:01   0:06 -
localad+ 17557  0.0  0.2   7288  4248 pts/0    -    фев26   0:00 man sudoedit
localad+     -  0.0    -      -     - -        S+   фев26   0:00 -
localad+ 17568  0.0  0.0   5592   904 pts/0    -    фев26   0:00 pager
localad+     -  0.0    -      -     - -        S+   фев26   0:00 -
...
Утилита pstree

С помощью утилиты pstree можно вывести дерево процессов. Для её использования необходим пакет psmisc sudo apt install psmisc.

localadmin@astra:~$ pstree
systemd─┬─3*[VBoxClient───VBoxClient───3*[{VBoxClient}]]
        ├─VBoxClient───VBoxClient───4*[{VBoxClient}]
        ├─VBoxDRMClient───4*[{VBoxDRMClient}]
        ├─VBoxService───8*[{VBoxService}]
        ├─agetty
        ├─alsactl
        ├─astra-orientati───2*[{astra-orientati}]
        ├─at-spi2-registr───2*[{at-spi2-registr}]
        ├─auditd───{auditd}
        ├─avahi-daemon───avahi-daemon
        ├─cron
        ├─cupsd
        ├─2*[dbus-daemon]
        ├─dbus-launch
        ├─dhclient───{dhclient}
        ├─fly-dm─┬─Xorg───{Xorg}
        │        └─fly-dm───fly-wm─┬─astra-event-wat───{astra-event-wat}
        │                          ├─at-spi-bus-laun─┬─dbus-daemon
        │                          │                 └─3*[{at-spi-bus-laun}]
        │                          ├─baloo_file───2*[{baloo_file}]
        │                          ├─fly-cups-watch───{fly-cups-watch}
        │                          ├─fly-notify-osd-───3*[{fly-notify-osd-}]
        │                          ├─fly-reflex-serv───3*[{fly-reflex-serv}]
        │                          ├─fly-search-pane───3*[{fly-search-pane}]
        │                          ├─fly-sound-apple───9*[{fly-sound-apple}]
        │                          ├─kscreend───2*[{kscreend}]
        │                          ├─nm-applet───3*[{nm-applet}]
        │                          ├─org_kde_powerde───6*[{org_kde_powerde}]
        │                          ├─polkit-kde-auth───4*[{polkit-kde-auth}]
        │                          ├─ssh-agent
        │                          └─x-terminal-emul─┬─bash───man───pager
        │                                            ├─bash───htop
        │                                            ├─2*[bash]
        │                                            ├─bash───pstree
        │                                            └─2*[{x-terminal-emul}]
        ├─fly-getexe
        ...

Ключ -p позволяет вывести PID процессов pstree -p.

localadmin@astra:~$ pstree -p
systemd(1)─┬─VBoxClient(1265)───VBoxClient(1266)─┬─{VBoxClient}(1267)
           │                                     ├─{VBoxClient}(1268)
           │                                     └─{VBoxClient}(1269)
           ├─VBoxClient(1280)───VBoxClient(1281)─┬─{VBoxClient}(1283)
           │                                     ├─{VBoxClient}(1284)
...

Поиск процессов

Утилита htop

Для поиска процессов в htop необходимо воспользоваться пунктом Search. Для этого нажмите клавишу F3. Вам станет доступна строка поиска. После выполнения поиска вы можете переходить от одного процесса к другому. Для выхода из режима поиска нажмите клавишу Esc.

../_images/alse_mod13_search.png

В целях поиска может использоваться и фильтрация. Она доступна по нажатию клавиши F4.

../_images/alse_mod13_filtering.png

Для очистки фильтра нажмите клавишу Esc.

Утилита ps

Для фильтрации вывода команды ps используйте встроенные опции: -123 или 123, -p "1 2" – вывод информации по PID процессу(ам).

localadmin@astra:~$ ps -1
   PID TTY      STAT   TIME COMMAND
   1 ?        Ss     0:08 /sbin/init
localadmin@astra:~$ ps 1
   PID TTY      STAT   TIME COMMAND
   1 ?        Ss     0:08 /sbin/init
localadmin@astra:~$ ps -p "1 2"
   PID TTY          TIME CMD
   1 ?        00:00:08 systemd
   2 ?        00:00:00 kthreadd

<имя_команды> – вывод информации по процессам, имя команды которых соответствует указанному, например, ps -C bash.

localadmin@astra:~$ ps -C bash
   PID TTY          TIME CMD
1468 pts/0    00:00:00 bash
1486 pts/1    00:00:00 bash
1493 pts/2    00:00:00 bash

Используя опцию -o pid, можно вывести только колонку с PID найденных процессов, а используя -o pid=, только PID без названия колонки.

localadmin@astra:~$ ps -C bash -o pid
   PID
1468
1486
1493
localadmin@astra:~$ ps -C bash -o pid=
1468
1486
1493

Другие опции фильтрации ps в справке man 1 ps.

Для дополнительной фильтрации можно использовать утилиту grep, например, ps aux | grep tty.

localadmin@astra:~$ ps aux | grep tty
root       753  0.0  0.0   5612  1656 tty1     Ss+  09:41   0:00 /sbin/agetty -o -p -- \u --noclear tty1 linux
root       778  0.0  3.1 912424 125044 tty7    Ssl+ 09:41   0:08 /usr/lib/xorg/Xorg -br -novtswitch -quiet -keeptty :0 vt7 -seat seat0 -auth /var/run/xauth/A:0-ZTNgnb
localad+  4933  0.0  0.0   6096   872 pts/0    S+   18:11   0:00 grep tty

Завершение процессов

При работе с утилитой htop для отправки сигнала процессу необходимо нажать F9. По умолчанию будет выбран сигнал SIGTERM. Для завершения процесса с этим сигналом необходимо нажать F9 и Enter (или перед нажатием Enter вы можете выбрать по необходимости другой сигнал).

Управление через графику в Системном мониторе

Системный монитор напоминает «Менеджер задач» в Windows, что было сделано специально для удобства пользователей и администраторов. Он имеет интуитивно понятный интерфейс и не должен вызвать сложностей при своем использовании.

../_images/alse_mod13_system_monitor_table.png

рис. 57 Системный монитор: таблица процессов

../_images/alse_mod13_system_monitor_util.png

рис. 58 Системный монитор: общая загрузка системы

Управление доступно через контекстное меню и органы управления. Для поиска процессов доступна строка быстрого поиска, для завершения процесса – соответствующая кнопка над списком задач. С помощью выпадающих списков вы можете отфильтровать процессы по категориям.

../_images/alse_mod13_system_monitor_filter.png

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

../_images/alse_mod13_sys_mon_menu.png ../_images/alse_mod13_sys_mon_priority.png

С подробной справкой вы можете ознакомиться в справочной системе Alt + F1.

Практика и тестирование

Заключение

В этом модуле мы узнали, что такое процессы и как устроен их жизненный цикл. Мы научились просматривать информацию о процессах и управлять ими. Теперь мы знаем, что такое зомби процессы и почему их не нужно бояться. Следующий модуль будет не настолько сложным. В нем мы познакомимся с вопросами архивирования.

Дополнительные источники информации