Что такое процесс в linux
Перейти к содержимому

Что такое процесс в linux

  • автор:

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

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

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

В этой статье будет затронута обширная тема, мы рассмотрим такие возможности:

  • Просмотр запущенных процессов
  • Просмотр информации о процессах
  • Поиск процессов в Linux
  • Изменение приоритета процессов
  • Завершение процессов
  • Ограничение памяти доступной процессу

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

Что такое процесс?

Начнем с того, что разберемся в терминах. По сути, процесс — это каждая программа. Как я уже говорил для каждой запускаемой программы создается отдельный процесс. В рамках процесса программе выделяется процессорное время, оперативная память и другие системные ресурсы. У каждого процесса есть свой идентификатор, Proccess ID или просто PID, по ним, чаще всего и определяются процессы Linux. PID определяется неслучайно, как я уже говорил, программа инициализации получает PID 1, а каждая следующая запущенная программа — на единицу больше. Таким образом PID пользовательских программ доходит уже до нескольких тысяч.

На самом деле, процессы Linux не настолько абстрактны, какими они вам сейчас кажутся. Их вполне можно попытаться пощупать. Откройте ваш файловый менеджер, перейдите в корневой каталог, затем откройте папку /proc. Видите здесь кучу номеров? Так вот это все — PID всех запущенных процессов. В каждой из этих папок находится вся информация о процессе.

Например, посмотрим папку процесса 1. В папке есть другие под каталоги и много файлов. Файл cmdline содержит информацию о команде запуска процесса:

Поскольку у меня используется система инициализации Systemd, то и первый процесс запускается для нее. С помощью каталога /proc можно сделать все. Но это очень неудобно, особенно учитывая количество запущенных процессов в системе. Поэтому для реализации нужных задач существуют специальные утилиты. Перейдем к рассмотрению утилит, которые позволяют реализовать управление процессами в Linux.

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

В Linux есть очень большое количество утилит для решения различных задач по управлению процессами. Это и такие многофункциональные решения, как htop, top, а также простые утилиты, например, ps, kill, killall, who и т д. Я не буду рассматривать в этой статье графические утилиты, и top тоже рассматривать не буду. Первое потому что слишком просто, второе — потому что htop лучше. Мы остановимся на работе с программой htop и ее аналогами в форме утилит в стиле GNU, одна утилита — одна функция.

Давайте установим htop, если она у вас еще не установлена. В Ubuntu это делается так:

sudo apt install htop

В других дистрибутивах вам нужно просто использовать свой менеджер пакетов. Имя пакета такое же.

Посмотреть запущенные процессы

Это очень простая задача, и также просто она решается. Для этого существует множество утилит, начиная от обычной ps, до более продвинутых интерактивных top, htop и так далее.

Открыв htop, мы сразу видим список запущенных процессов. Конечно, здесь отображены не все процессы linux, их-то в системе очень много, вы уже знаете, все они на один экран не поместятся. По умолчанию выводятся процессы, запущенные от имени вашего пользователя:

htop

Вы можете увидеть такую информацию о процессе:

  • PID — идентификатор процесса
  • USER — пользователь, от которого был запущен процесс
  • PRI — приоритет процесса linux на уровне ядра (обычно NI+20)
  • NI — приоритет выполнения процесса от -20 до 19
  • S — состояние процесса
  • CPU — используемые ресурсы процессора
  • MEM — использованная память
  • TIME — время работы процесса

К отображению можно добавить и дополнительные параметры, но эти главные. Добавить параметры можно с помощью меню Setup. Там все очень просто, читайте подсказки и следуйте указаниям. Например, добавлен параметр PPID:

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

htop2

Также есть интересная возможность разместить процессы в виде дерева. Вы сможете увидеть, каким процессом был запущен тот или иной процесс. Для отображения дерева нажмите кнопку F5:

htop3

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

ps

Рассмотрим основные опции, которые будем использовать:

  • -e — вывести информацию обо всех процессах
  • -a — вывести информацию обо всех наиболее часто запрашиваемых процессах
  • -t — показывать только процессы из этого терминала
  • -p — показывать информацию только об указанном процессе
  • -u — показывать процессы только определенного пользователя

Одним словом, чтобы посмотреть все активные на данный момент процессы в linux, используется сочетание опций aux:

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

Список будет отсортирован в обратном порядке, внизу значения больше, вверху — меньше. Если нужно в обратном порядке, добавьте минус:

ps1

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

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

pstree

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

Список процессов, это хорошо. Но иногда, когда какой-нибудь процесс завис и нужно убить процесс Linux или нам нужно провести с ним какие-либо действия, нужно выделить этот процесс из списка, узнать его PID и информацию о нем.

Чтобы найти процесс linux в htop можно использовать кнопку F3. Нажмите F3 и наберите нужное слово. Дальше чтобы перейти к следующему вхождению нажимайте F2 или Esc для завершения поиска:

htop4

Для поиска процессов в htop можно использовать также фильтр htop. Нажмите F4, введите слово и будут выведены только процессы linux, имя которых включает это слово.

htop6

В утилите ps фильтрации нет, но зато мы можем использовать утилиту grep, перенаправив вывод ps на нее чтобы найти процесс linux:

ps aux | grep chromium

Это очень часто употребляемая команда.

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

Приоритет процесса linux означает, насколько больше процессорного времени будет отдано этому процессу по сравнению с другими. Так мы можем очень тонко настроить какая программа будет работать быстрее, а какая медленнее. Значение приоритета может колебаться от 19 (минимальный приоритет) до -20 — максимальный приоритет процесса linux. Причем, уменьшать приоритет можно с правами обычного пользователя, но чтобы его увеличить нужны права суперпользователя.

В htop для управления приоритетом используется параметр Nice. Напомню, что Priv, это всего лишь поправка, она в большинстве случаев больше за Nice на 20. Чтобы изменить приоритет процесса просто установите на него курсор и нажимайте F7 для уменьшения числа (увеличения приоритета) или F8 — для увеличения числа.

Но и для решения этой задачи управления процессами Linux необязательно использовать htop. Вы можете сделать все и другими командами. Например, команда nice. С помощью нее вы можете указать приоритет для запускаемого процесса:

nice -n 10 apt-get upgrade

Или изменить приоритет для уже существующего по его pid:

renice -n 10 -p 1343

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

Если процесс завис и не отвечает, его необходимо завершить. В htop, чтобы убить процесс Linux, просто установите курсор на процесс и нажмите F9:

htop7

Система для управления процессами использует определенные сигналы, есть сигналы, которые указывают процессу завершиться. Вот несколько основных сигналов:

  • SIGTERM — попросить процесс сохранить данные и завершится
  • SIGKILL — завершить процесс немедленно, без сохранения

Вообще сигналов есть несколько десятков, но мы не будем их рассматривать. Отправим сигнал SIGKILL:

Также можно воспользоваться утилитой kill:

Также можно уничтожить процесс по имени:

Ограничение процессов

Управление процессами в Linux позволяет контролировать практически все. Вы уже видели что можно сделать, но можно еще больше. С помощью команды ulimit и конфигурационного файла /etc/security/limits.conf вы можете ограничить процессам доступ к системным ресурсам, таким как память, файлы и процессор. Например, вы можете ограничить память процесса Linux, количество файлов и т д.

Запись в файле имеет следующий вид:

<домен> <тип> <элемент> <значение>

  • домен — имя пользователя, группы или UID
  • тип — вид ограничений — soft или hard
  • элемент — ресурс который будет ограничен
  • значение — необходимый предел

Жесткие ограничения устанавливаются суперпользователем и не могут быть изменены обычными пользователями. Мягкие, soft ограничения могут меняться пользователями с помощью команды ulimit.

Рассмотрим основные ограничения, которые можно применить к процессам:

  • nofile — максимальное количество открытых файлов
  • as — максимальное количество оперативной памяти
  • stack — максимальный размер стека
  • cpu — максимальное процессорное время
  • nproc — максимальное количество ядер процессора
  • locks — количество заблокированных файлов
  • nice — максимальный приоритет процесса

Например, ограничим процессорное время для процессов пользователя sergiy:

sergiy hard nproc 20

Посмотреть ограничения для определенного процесса вы можете в папке proc:

Max cpu time unlimited unlimited seconds Max file size unlimited unlimited bytes Max data size unlimited unlimited bytes Max stack size 204800 unlimited bytes Max core file size 0 unlimited bytes Max resident set unlimited unlimited bytes Max processes 23562 23562 processes Max open files 1024 4096 files Max locked memory 18446744073708503040 18446744073708503040 bytes Max address space unlimited unlimited bytes Max file locks unlimited unlimited locks Max pending signals 23562 23562 signals Max msgqueue size 819200 819200 bytes Max nice priority 0 0 Max realtime priority 0 0 Max realtime timeout unlimited unlimited us

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

Вот опции команды:

  • -S — мягкое ограничение
  • -H — жесткое ограничение
  • -a — вывести всю информацию
  • -f — максимальный размер создаваемых файлов
  • -n — максимальное количество открытых файлов
  • -s — максимальный размер стека
  • -t — максимальное количество процессорного времени
  • -u — максимальное количество запущенных процессов
  • -v — максимальный объем виртуальной памяти

Например, мы можем установить новое ограничение для количества открываемых файлов:

Установим лимит оперативной памяти:

ulimit -Sv 500000

Напоминаю, что это ограничение будет актуально для всех программ, выполняемых в этом терминале.

Выводы

Вот и все. Теперь управление процессами в Linux не вызовет у вас проблем. Мы рассмотрели очень даже подробно эту тему. Если у вас остались вопросы или есть предложения по дополнению статьи, пишите в комментариях!

Похожие записи

Оцените статью

alt=»Creative Commons License» width=»» />
Статья распространяется под лицензией Creative Commons ShareAlike 4.0 при копировании материала ссылка на источник обязательна .

Об авторе

Основатель и администратор сайта losst.ru, увлекаюсь открытым программным обеспечением и операционной системой Linux. В качестве основной ОС сейчас использую Ubuntu. Кроме Linux, интересуюсь всем, что связано с информационными технологиями и современной наукой.

9 комментариев к “Управление процессами в Linux”

Очень интересно, вот так «с налёта» разобраться не получится, придётся неоднократно возвращаться.
Вы подняли в этот раз очень интересную и важную тему, тем более, что к ней обращаются и не так уж и часто.
С благодарностью, Р.

Но вот все остальное для может показаться сложным «вас»?

Исправил эту и еще несколько ошибок. Спасибо!

А можно ли по названию программы выявить ID процесса и потом вызвать kill указав этот ID ?
Чтобы это было одной командой или bash скрипт.
Цель в том, чтобы в cron записать остановку и запуск программы по расписанию.
Заранее спасибо!

возможно приоритеты от (-19) до (20). Просто сколько лазил не увидел ни 1 процесса ниже -19 (и не смог ни 1 таковым сделать), и у половины моих процессов стоит приоритет 20.

«Чтобы найти процесс linux в htop можно использовать кнопку F3. Нажмите F3 и наберите нужное слово. Дальше чтобы перейти к следующему вхождению нажимайте F2 или Esc для завершения поиска:»

F2 на F3 поменяйте. Опечатались.
Статья отличная. Кратко и по сути. Мне, как нубу, очень помогло.

«SIGKILL — попросить процесс сохранить данные и завершится
SIGTERM — завершить процесс немедленно, без сохранения»

вообще-то наоборот )
sigkill — убить процесс без сохранения (код -9)
sigterm — попросить процесс завершить все начатое и закрыться (код -15)

Как открыть уже запущенный процесс, чтобы он отобразился на экране?
Я частенько закрываю процесс, он становится своего рода скрытым, а как его достать не понимаю. Если в Windows процесс остаётся в трее и его всегда можно снова открыть, то как это сделать в Ubuntu? Спасибо

Процессы в Linux

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

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

Просмотр текущих процессов

Самый простой способ посмотреть список процессов, запущенных в текущей командой оболочке(на сервере), использовать команду ps без параметров:

Вот значение основных колонок в выводе утилиты:

UID — имя пользователя, от имени которого работает процесс;

PID — идентификатор пользователя;

PPID — идентификатор родительского процесса пользователя;

C — расходование ресурсов процессора, в процентах;

SZ — размер процесса;

RSS — реальный размер процесса в памяти;

PSR — ядро процессора, на котором выполняется процесс;

STIME — время, когда процесс был запущен;

TTY — если процесс привязан к терминалу, то здесь будет выведен его номер;

TIME — общее время выполнения процесса (user + system);

CMD — команда, которой был запущен процесс, если программа не может прочитать аргументы процесса, он будет выведен в квадратных скобках;

Чтобы посмотреть список процессов в виде дерева, и понимать какой процесс имеет какие дочерние процессы, можно выполнить команду:

Чтобы посмотреть все активные на данный момент процессы в linux, используется сочетание опций aux :

Также чтобы просматривать список запущенных процессов в режиме реального времени, можно использовать утилиту top , которая выводит список процессов:

Чтобы отслеживать список процессов конкретного пользователя на сервере:

Колонки, которые выводит программа очень похожи на ps:

PID — идентификатор процесса;

USER — имя пользователя, от имени которого выполняется процесс;

PR — приоритет планировщика, установленный для процесса;

NI — рекомендуемый приоритет процесса. Это значение можно менять, может не совпадать с реальным приоритетом планировщика;

VIRT — всё, что находится в памяти, используется или зарезервировано для использования;

RES — всё, что находится в оперативной памяти и относится к процессу. Расшифровывается как Resident Memory Size, указывается в килобайтах;

SHR— часть памяти из RES, которую занимают ресурсы, доступные для использования другим процессам. Расшифровывается — Shared Memory Size. S — состояние процесса: D — ожидает завершения операции, R — запущен, S — спит, T — остановлен, t — остановлен отладчиком, Z — зомби;

%CPU — процент использования ресурсов процессора;

%MEM — процент использования ресурсов оперативной памяти на основе колонки RES;

TIME — обще процессорное время, которое процесс использовал с момента запуска;

COMAND — команда, с помощью которой был запущен процесс.

Выход из top — клавиша q.

Другое

Ещё более мощная утилита для просмотра запущенных процессов в Linux — htop. Пользоваться ею намного удобнее. Здесь поддерживаются не только горячие клавиши, но и управление мышью. А ещё она выводит всё в цвете, поэтому смотреть на данные намного приятнее.

Смотреть запущенные процессы можно не только в терминале, но и в графическом интерфейсе. Для этого можно использовать утилиту Gnome Monitor.

Переключение процессов, запуск в фоне

Программа может находится в основном режиме ( fg ) или в фоновом ( bg ). Различие этих режимов состоит в том, что в фоновом режиме можно запустить несколько(неограниченное число) программ (+ команды, введённые в терминал также будут выполняться), в то время как в активном режиме может находиться только 1 программа. Также различие заключается в том, что при закрытии терминала программа в фоновом режиме не закроется, а в активном — закроется.

Чтобы посмотреть все запущенные фоновые программы используется команда jobs . Для каждой программы показывается её статус: running — запущено, suspended — приостановлено( fg и ctrl Z), stopped, done, exit.

Чтобы запустить определённую программу в фоновом режиме нужно добавить & в конце имени программы или .

fg выводит программу из фонового режима.

fg % номер команды или (аналогично bg) — продолжить программу с данным номером(вывести из фонового режима).

Просто fg выведет последнюю добавленную в фоновый режим программу ( в jobs помечена знаком +)

Также программы можно по-разному завершать, приостанавливать, продолжать в разных режимах:

  • Например, сочетание клавиш Ctrl C прерывает выполнение текущей программы (контролируется сигналом SIGINT). Программа может избежать закрытия перехватив сигнал (например, питоном и OC).
  • Также прервать выполнение программы можно с помощью Ctrl \ ( контролируется SIGQUIT, который нельзя перехватить питоном, но можно oc(сложнее, тк сразу закрывает)).
  • Сочетание клавиш Ctrl D завершает сессию.
  • ctrl z — приостановка, далее можно продолжить программу ( fg ) или продолжить в фоновом режиме ( bg ); контролируется сигналом SIGTSP.

Пример реализации: gedit закрывается ctrl c (и команды введенные в терминал, пока был запущен firefox). Если ввести ctrl z — программа не реагирует на нажатия. Если после этого ввести fg — произойдет выполнение всех команд, которые были введены и нет реакции в терминале; bg — программа реагирует на нажатия и также выполняются команды в терминале.

Завершить процесс на сервере можно с помощью команды kill ( контролируется SIGTERM, который можно перехватить OC).

После команды kill программа не отображается в ps.

В самом крайнем случае используют kill -9 (контролируется сигналом SIGKILL, который нельзя перехватить).

Эту команду используют, чтобы убить программу(если завис).

Выводы

Таким образом, мы рассмотрели процессы в линуксе, научились просматривать процессы в системе и текущие процессы, рассмотрели внешний контроль над процессами.

Unix2017b/Процессы

Основными активными сущностями в операционной системе являются процессы. Каждый процесс выполняет одну программу и изначально получает один поток управления. Иначе говоря, у процесса есть один счетчик команд, который отслеживает следующую исполняемую команду. ОС позволяет процессу создавать дополнительные потоки (после того, как он начинает выполнение).

Linux представляет собой многозадачную систему и несколько независимых процессов могут работать одновременно. Более того, у каждого пользователя может быть одновременно несколько активных процессов, так что в большой системе могут одновременно работать сотни и даже тысячи процессов. Фактически на большинстве однопользовательских рабочих станций (даже когда пользователь куда-либо отлучился) работают десятки фоновых процессов, называемых демонами (daemons).

Типичным демоном является cron.

Просмотр списка процессов

ps (process status) — программа в UNIX-системах, выводящая отчёт о работающих процессах.

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

Опции разных видов:

  1. UNIX options (начинаются с -)
  2. BSD options (без -)
  3. GNU long options (--)

Так, например, ключи -e (с минусом) и ax (без минуса) полностью эквивалентны.

Пример — получить имя процесса по PID:

pgrep

Поиск процесса по имени — регулярному выражению. По умолчанию используется синтаксис ERE.

примерно эквивалентно такому:

pidof

Аналогично, поиск по имени.

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

ps же формирует вывод и завершается. Можно следить за выводом при помощи команды watch:

Чтобы выйти из программы top, нужно нажать клавишу q.

Предоставляет пользователю текстовый интерфейс; для вывода на терминал использует библиотеку ncurses.

Автор (Hisham Muhammad) назвал программу «htop» по аналогии с тем, как названа программа «pinfo», написанная программистом по имени Przemek Borys. Слово «pinfo» означает «Przemek’s info». Слово «htop» означает «Hisham’s top».

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

Подходит для долговременного мониторинга ресурсов сервера, умеет писать лог.

iotop

Мониторинг ввода/вывода. Нужно запускать от root.

pstree

Рисует дерево процессов.

procfs

procfs — виртуальная файловая система, используемая в Unix-подобных операционных системах. Позволяет получить доступ к информации из ядра о системных процессах. Обычно её монтируют на /proc. procfs создает двухуровневое представление пространств процессов. На верхнем уровне процессы представляют собой директории, именованные в соответствии с их pid. Также на верхнем уровне располагается ссылка на директорию, соответствующую процессу, выполняющему запрос; она может иметь различное имя в различных ОС (curproc во FreeBSD, self в Linux).

GNU-версия утилиты ps читает всю информацию о процессах из /proc, не делая каких-то специальных системных вызовов.

На Linux из procfs можно получить такую информацию о каждом процессе (перечислим отдельные пункты):

  • /proc/PID/cmdline — командная строка, использованная при запуске процесса.
  • /proc/PID/cwd — симлинк на текущий рабочий каталог процесса.
  • /proc/PID/environ содержит имена и значения переменных окружения.
  • /proc/PID/exe — симлинк на оригинальный исполняемый файл.
  • /proc/PID/fd — каталог, содержащий симлинки на все открытые файловые дескрипторы.
  • /proc/PID/maps — текстовый файл, описывающий адресное пространство (куча, стек, заммапленные файлы).
  • /proc/PID/status содержит базовую информацию о процессе, включая текущий статус и потребление памяти.

Кроме того, есть общая информация, не привязанная к отдельным PID.

  • /proc/cpuinfo — модель, тактовая частота процессора.
  • /proc/meminfo — сведения об использовании памяти.
  • /proc/uptime — время с момента загрузки ядра и время в простое (idle time), в секундах.

И многое другое.

Практически весь контент генерируется ядром на лету при чтении «файлов», поэтому их размер может отображаться как равный нулю. Данные не хранятся на диске (в файловой системе ext2/3/4 и пр.). Программа stat отображает для этих «файлов» всегда свежайшее время модификации.

Идентификатор процесса (process identifier, PID) — уникальный номер (идентификатор) процесса в многозадачной операционной системе (ОС).

Как правило, PID’ы выдаются последовательно от 0. По достижении лимита счёт снова начинается с 300 (в Mac OS X — со 100). Это сделано отчасти для ускорения, потому что малые PID часто заняты системными процессами.

Часто имеется два специальных значения PID: swapper или sched — процесс с номером 0 (часто не отображается в списке), отвечает за выгрузку страниц и является частью ядра операционной системы. Процесс 1 — обычно является процессом init, ответственным за запуск и остановку системы.

В C-коде: тип данных pid_t (на самом деле определён как int ).

Приятно, обрабатывать ошибочный код возврата не нужно. «These functions are always successful.»

Ограничение числа процессов

На старых Linux (до 2.4) ограничение на PID было фиксированное — 32767.

В современной системе лимит настраивается. На 64-битном Linux ограничение на число процессов можно поднять до [math]2^<22>[/math] .

Файл /etc/security/limits.conf. Можно добавить строку вида

Родительский процесс

Процессы организованы в виде дерева. У каждого процесса, кроме нулевого, есть ровно один родительский процесс.

Состояние процесса

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

  • D — uninterruptible sleep (обычно I/O)
  • R — running or runnable (в очереди на выполнение)
  • S — interruptible sleep (ожидает какого-то события)
  • T — stopped by job control signal
  • t — stopped by debugger during the tracing
  • W — paging (не бывает начиная с ядер 2.6.xx)
  • X — dead (никогда не должно встречаться)
  • Z — defunct («zombie») process (рассмотрим далее)

Приоритет

Утилита nice, запущенная без аргументов, выводит приоритет nice, унаследованный от родительского процесса. nice принимает аргумент «смещение» в диапазоне от -20 (наивысший приоритет) до +19 (низший приоритет). nice может запустить команду с заданным смещением. Если смещение не указано, будет использовано смещение +10. Привилегированный пользователь (root) может указать отрицательное смещение.

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

Конкретный эффект от значений nice зависит от реализации планировщика в ядре ОС.

Приоритет nice и приоритет планировщика процессов ядра ОС — разные числа. Число nice — приоритет, который пользователь хотел бы назначить процессу. Приоритет планировщика — действительный приоритет, назначенный процессу планировщиком. Приоритет nice является атрибутом процесса и, как и другие атрибуты, наследуется дочерними процессами. В выводе утилит top, ps, htop и др. приоритет nice называется «NI» — сокращение от «nice», а приоритет планировщика — «PRI» — сокращение от «priority». Обычно, NI = PRI — 20, но это верно не всегда. По умолчанию NI=0, соответственно PRI=20.

  • Утилита nice задаёт приоритет новосоздаваемому процессу. Для изменения приоритета уже запущенных процессов используется утилита renice.
  • В Linux есть также утилита ionice, которая влияет на планировщик I/O-операций, а не на распределение времени процессора.

Как работает планировщик

Версии

До выхода ядра Linux версии 2.6 планировщик имел существенное ограничение, проявлявшееся при большом количестве выполняющихся задач. Причиной тому был алгоритм планировщика, имевший сложность [math]O(n)[/math] . Алгоритму не хватало масштабируемости. Кроме того, плохо учитывались особенности многопроцессорных систем, на очередь задач брался глобальный лок.

В версии 2.6 появился новый планировщик, который все операции выполнял за константное время [math]O(1)[/math] .

Затем в версии 2.6.23 (в октябре 2007) создан новый планировщик. Алгоритм получил название Completely Fair Scheduler (CFS). В нём выбор новой задачи для исполнения делается за [math]O(1)[/math] , а возврат задачи в очередь выполняется за [math]O(\log n)[/math] . В реализации используется красно-чёрное дерево.

CFS используется в Linux сегодня. Доработки в планировщик продолжаются. Так, в ноябре 2010 в ядре 2.6.38 добавили патч (autogrouping), который сделал планировщик «честнее» и сильно улучшил производительность десктопных систем.

Как учитывается значение nice

Влияние числа nice экспоненциально. Примерно так:

  • уменьшение числа на 1 — на 10% больше CPU,
  • увеличение числа на 1 — на 10% меньше CPU.

Вес вычисляется по формуле [math]\frac<1024><1.25^<\mathrm>>[/math] .

  • weight is 1024 for nice value 0
  • weight is 820 for nice value 1
  • weight is 1277 for nice value -1

Упрощённо говоря, планировщик суммирует веса по всем процессам, затем раздаёт время CPU в нужной пропорции (отношение веса процесса к сумме весов).

Realtime-приоритеты

В выводе команды ps можно найти так называемые scheduling class’ы (классы планирования):

Можно заметить, что почти все процессы в системе имеют класс TS (other). На что они влияют?

SCHED_FIFO и SCHED_RR являются так называемыми политиками реального времени. Они реализуют реалтайм-планирование с фиксированными приоритетами, как требует стандарт POSIX. Задачи с этими политиками вытесняют любую другую задачу, и, если они не освобождают вовремя процессор, другие задачи могут легко впадать в starvation (голод).

  • SCHED_FIFO: политика планирования реального времени «первый вошёл, первый вышел» (First-In First-Out). Алгоритм планирования не использует никаких интервалов времени. Процесс SCHED_FIFO выполняется до завершения, если он не заблокирован запросом ввода/вывода, вытеснен высокоприоритетным процессом, или он добровольно отказывается от процессора.
  • SCHED_RR: циклическая (Round-Robin) политика планирования реального времени. Она похожа на SCHED_FIFO с той лишь разницей, что процессу SCHED_RR разрешено работать как максимум время кванта. Если процесс SCHED_RR исчерпывает свой квант времени, он помещается в конец списка с его приоритетом. Процесс SCHED_RR, который был вытеснен процессом с более высоким приоритетом, завершит оставшуюся часть своего кванта времени после возобновления выполнения.
  • SCHED_OTHER — это общая политика планирования (не realtime), которая планирует задаче определённый квант времени в зависимости от других задач, выполняемых в системе.

Вам почти никогда не нужно запускать ваш пользовательский код с realtime-приоритетом! Если выполнять в realtime вычислительно тяжёлый код, который активно использует CPU, другим процессам может совсем не достаться, вся машина начнёт сильно тормозить. Для процессов, которые много ждут и которым важно время до пробуждения, такой приоритет может быть полезен.

Для установки realtime-приоритета используется утилита chrt, а не nice.

Приоритеты задаются от 1 (минимальный) до 99 (максимальный).

Назначение процессов на ядра

С распространением многоядерных процессоров и многопроцессорных материнских плат вопрос стал актуален. Указание для процесса множества ядер, на которых ему следует выполняться, называется CPU affinity.

В Linux используется утилита taskset или numactl.

Процессы-демоны

<barmholio> да-да-да, винда — это самая православная ОС, потому что в ней есть иконы и службы, а не демоны и зомби, как в юниксах :) bash.im

Демон (daemon, dæmon, божество) — программа в ОС семейства Unix, запускаемая самой системой и работающая в фоновом режиме без прямого взаимодействия с пользователем.

Демоны обычно запускаются во время загрузки системы. Типичные задачи демонов: серверы сетевых протоколов (HTTP, FTP, электронная почта и др.), управление оборудованием, поддержка очередей печати, управление выполнением заданий по расписанию и т.д. В техническом смысле демоном считается процесс, который не имеет управляющего терминала. Чаще всего (но не обязательно) предком демона является init — корневой процесс UNIX.

В системах Windows аналогичный класс программ называется службой (Services).

Название «демон» появилось ещё до Unix, в 1960-x годах в системе Project MAC. Названо в честь демона Максвелла из физики, занимающегося сортировкой молекул в фоновом режиме. Демон также является персонажем греческой мифологии, выполняющим задачи, за которые не хотят браться боги.

Процесс init

init (сокращение от initialization) — система инициализации в Unix-подобных системах, которая запускает все остальные процессы.

  • Первый пользовательский процесс, работает как демон и обычно имеет PID 1.
  • Запускается непосредственно ядром системы.
  • Является пра-родителем всех пользовательских (userspace) процессов системы.
  • Согласно Filesystem Hierarchy Standard, располагается по пути /sbin/init.

runlevels

Уровень выполнения (runlevel) — степень загрузки операционной системы. Вот как происходит инициализация системы: процесс init запускается и анализирует файл /etc/inittab. Следует отметить, что в BSD-подобных системах схема несколько отличается.

Пример файла /etc/inittab:

По умолчанию в системе использовано 7 уровней инициализации:

  • 0 — остановка системы
  • 1 — загрузка в однопользовательском режиме
  • 2 — загрузка в многопользовательском режиме без поддержки сети
  • 3 — загрузка в многопользовательском режиме с поддержкой сети
  • 4 — не используется
  • 5 — загрузка в многопользовательском режиме с поддержкой сети и графического входа в систему
  • 6 — перезагрузка

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

В большинстве Unix/Linux систем, узнать текущий уровень инициализации можно командами:

$ runlevel $ who -r

Набрав init n в терминале (с правами суперпользователя), где n — номер уровня инициализации, можно переключиться в любой из вышеперечисленных уровней.

Стартовые скрипты для каждого уровня находятся в каталогах с /etc/rc0.d до /etc/rc6.d, где цифра после rc соответствует номеру уровня инициализации.

Обычно скрипты не дублируются для каждого уровня. В каталогах rcX просто ставятся симлинки на скрипты в /etc/init.d.

Сами скрипты в /etc/init.d обычно пишутся по шаблону и должны уметь принимать параметр start|stop|restart.

В именовании используется такая логика.

  • S — скрипты для запуска (start)
  • K — скрипты для остановки (stop)
  • Номер задаёт порядок выполнения: чем меньше номер, тем раньше запускается скрипт.

Для автоматизации создания этих линков с правильными именами есть специальные утилиты. Например, в RedHat и Fedora используется программа chkconfig, в Debian — update-rc.d.

Есть также специальный скрипт /etc/rc.local, который выполняется во всех многопользовательских уровнях.

Современные альтернативы init

Сейчас существует множество систем, призванных заменить собой классический init.

Главный недостаток традиционного init — он запускал процессы последовательно, ожидая завершения предыдущего перед запуском следующего. Поэтому были разработаны альтернативные решения:

Name already in use

LinuxNotes / Linux Process.md

  • Go to file T
  • Go to line L
  • Copy path
  • Copy permalink
  • Open with Desktop
  • View raw
  • Copy raw contents Copy raw contents

Copy raw contents

Copy raw contents

Процесс — исполняемый экземпляр программы. Процессы могут быть порождены другими процессами, породить ещё процессы, умереть или быть убитыми. Когда процесс создаётся, он почти идентичен своему родителю: получает копию адресного пространства процесса-родителя на момент создания ребёнка. У отца и ребёнка свои собственные данные(стек, куча, структуры данных, код(возможно) — копия), потому изменение ребёнком своих данных не видно родителю и наоборот.

Во время эволюции Unix систем появились пользовательские POSIX потоки — pthread, которые совместно используют большое количество структур данных. Однако первоначальная реализация потоков была не очень удачна, что связано с тем что их планировкой занимались пользователи. Тогда были созданы облегчённые процессы. По сути те же потоки, только их планирование осуществляется ядром и, как следствие, их проще синхронизировать. Сейчас c каждым потоком ассоциирован облегчённый процесс.

В Linux есть такое понятие, как группа потоков — набор облегчённых процессов, которые действуют, как единое целое по отношению к системам вызовам: getpid(), kill(), _exit().

Каждый процесс(облегчённый тоже) описывается с помощью структуры struct task_struct(task_t). Структура полностью описывает всё состояние, атрибуты процесса и многое другое, и она ОЧЕНЬ большая, её описание можно найти в файле include/linux/sched.h.

task_struct
thread_info
state /*-1 unrunnable, 0 runnable, >0 stopped */
*stack
usage
flags
sched_info sched_info
mm_struct mm / Указатели на дескрипторы областей памяти*/
mm_struct *active_mm
pid_t pid /* Идентификатор процесса*/
pid_t tgid /* Идентификатор группы процесса*/
parent / recipient of SIGCHLD, wait4() reports */
real_parent / real parent process */
list_head children /* list of my children */
fs_struct fs / filesystem information */
files_struct files / open file information */
/* signal handlers */
list_head sibling; /* linkage in my parent’s children list */
list_head tasks /* Общий список процессов*/
……………

Рассмотрим некоторые поля:

  1. @parent — это тот task, которому надо отправлять уведомления (например, сигнал SIGCHLD) о данном task_struct.
  2. @real_parent — всегда тот task_struct, который породил данный task. В большинстве случаев parent == real_parent. Но если мы подцепились к task_struct-у отладчиком, то parent-ом будет отладчик.
  3. @children — список из детей данного task_struct-а.
  4. @sibling — list_head-узел в списке (см. описание списков list_head) children твоего родителя
  5. @tasks — list_head-узел в списке всех процессов (голова находится в idle-таске). В ядре иногда возникают задачи, когда нужно перебрать все процессы в системе (например, чтобы найти жертву, когда памяти не хватает, см. mm/oom_kill.c) соответственно, для данного перебора можно написать поиск в глубину (в ширину), зная родственные отношения процессов в ядре, однако в ядре особо не заморачиваются, поэтому проходятся по списку tasks.

Процесс может находится в различных состояниях во время своего существования. Например:

Процесс либо выполняется, либо готов в любой момент выполняться и ждёт своего времени.

Процесс приостановлен, пока не произойдёт определённое событие, которое должно его разбудить (например, пришли данные в pipe, а объект pipe знает, кто его ждет, pipe и занимается пробуждением процесса из состояния INTERRUPTIBLE). Также из этого состояния процесс пробуждается, если приходит сигнал.

Это состояние похоже на предыдущее, но приход сигнала не пробуждает процесс (даже SIGKILL не разбудит), процесс в этом состоянии прервать нельзя. Используется редко, когда ожидаемое событие долго ждать, но оно гарантированно конечно. Например, чтение файлов устройств(IO), времени, взятие mutex.

Процесс переходит в это состояние после получения сигнала SIGSTOP и похожих.

У каждого процесса есть поле — int exit_state, которое содержит состояние, с которым процесс завершил своё выполнение. После того, как процесс завершает работу ядро переводит его в состояние «Зомби»:

В состояние «Зомби» процесс будет находиться до тех пор, пока его родитель не прочитает его состояние с помощью wait4(), waitpid() и т.д.

Последнее состояние жизни процесса, в которое он переходит после того, как кто-нибудьвыполнит к нему wait4, waitpid().

Схема состояний и переходов между ними процесса; о состоянии процесса можно узнать с помощью утилиты ps:

Состояния R (running), r/q (ready, queued), W/S(wait/sleep) — для userspace В ядре состояния R, r/q объединяются в RUNNING.

Максимальное количество процессов обычно 2^15 = 32768. По умолчанию можно получить из макроса #define PID_MAX_DEFAULT (CONFIG_BASE_SMALL ? 0x1000 : 0x8000) (include/linux/threads.h). Так же количество доступных процессов может быть изменено системным администратором в /proc/sys/kernel/pid_max/. На 64 разрядных машинах максимальное значение можно увеличить до 4 * 1024 * 1024.

Для повторного использования pid’ов ядро поддерживает pidmap(include/linux/ pid_namespace.h)

task_struct существует для каждого процесса, даже облегчённого, pid у них у всех разный. Однако с потоками надо работать, как с единой сущностью, например, посылая сигнал. Потому у каждого потока в группе есть общий идентификатор — pid лидера группы и хранится он в поле tgid (thread group id), и системный вызов getpid() возвращает именно его.

Для каждого процесса ядро хранила struct thread_info, содержащую указатель на task_struct, и стэк режима ядра. thread_info — платформозависимая структура, потому искать её в <asm/thread_info.h>. Для x86 для ядра 2.6 выглядела вот так:

Раньше размер стэка ядерного режима был 4Кб и task_struct хранился в нём.

Для 32битной системы sizeof(task_struct)

1.7 Kb, что было довольно критично, поэтому ввели thread_info, который указывает на task_struct, также увеличили стэк ядерного режима до 8Kb.

Однако в процессе эволюции thread_info переместилось в окончательно в task_struct, а на структуру указывает регистр gs.

Текущий процесс, запущенный на процессоре можно получить с помощью макроса current() <asm/current.h>:

Так же надо заметить, что thread_info должна быть самой первой в task_struct, чтобы имея адрес одной в регистре fs, иметь адрес двух структур сразу, что можно заметить в макросе:

Списки процессов: Для дальнейшего понимания происходящего необходимо разобраться со списками Linux и технологией RCU. Вы сможете это сделать прочитав, например, соседние файлы: Linux Lists.txt и Linux Synchronization.txt

Все процессы выстроены в двунаправленный список, для этого каждая структура task_struct включает в себя поле — struct list_head tasks. В голове списка находится дескриптор init_task с pid = 0.

Пройтись по списку процессов можно с помощью макроса for_each_process(p) (include/linux/sched.h):

При создании процесса, новый добавляется в конец списка процессов (kernel/fork.c —> copy_procces):

Изучив структуру task_struct, мы можем отыскать ещё списки в её составе:

Данные списки описывают какие отношения связывают наш процесс с другими процессами. Список — children содержит детей нашего процесса, а sibling — братьев — других процессов созданных нашим родителем.

Процесс 0 — предок всех процессов. Его описывает статическая структура: struct task_struct init_task = INIT_TASK(init_task); (/init/init_task.c и макрос в/linux/init_task.h)

Структура инициализируется при старте функцией — start_kernel(void) (/init/main.c). После чего процесс 0 инициализирует подсистемы, создаёт процесс с pid == 1 — init.

Функция kernel_thread(kernel_init, NULL, CLONE_FS) — создаст клона, который будет исполнять функцию kernel_init. После этого процесс 0 вызовет cpu_idle() и будет работать вхолостую, просыпаясь только если другие процессы не могут быть исполнены. Созданный поток ядра завершает инициализацию ядра, а после загружает исполняемую программу init.

Как мы видели раньше у каждого процесса может быть группа потоков исполнения. У каждого потока свой собственный pid, но все потоки должны реагировать на событие, как одна сущность потому есть tgid = pid лидера группы потоков.

Различные процессы объединяются в группы процессов, для того чтобы взаимодействовать с ними, как с единой сущностью есть pgid = pid процесса лидера. В группу процессов входят не только родственники, но и процессы объединённые с помощью конвейера process | process …

Группы процессов в свою очередь объединяются в сессию, сессии связаны с терминалом. И, как можно догадаться, sid = pid лидера сессии.

Для удобства и скорости управления процессами на этапе инициализации ядра создаётся 4 хэш-таблицы: для каждого потока (различные pid), для каждого лидера группы(tgid = pid), для каждого лидера группы процессов(pgid = pid), для каждого лидера сессии(sid = pid).

Хэш таблица эффективнее массива работает с памятью, так как количество процессов в системе зачастую меньше чем их максимальное количество.

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

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