Команда ps в linux

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

Сердцем всех Linux и Unix-подобных операционных систем является ядро. Среди его многочисленных обязанностей — распределение системных ресурсов, таких как оперативная память и процессорное время. Они должны выполняться в режиме реального времени, чтобы все запущенные процессы получали свою справедливую долю в соответствии с приоритетом каждой задачи.

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

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

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

Вычисление средней загрузки

Средняя загрузка (Load Average, LA) — усредненная мера использования ресурсов компьютера запущенными процессами. Величина LA пропорциональна числу процессоров в системе и на ненагруженной системе колеблется от нуля до значения, равного числу процессоров. Высокие значения LA (10*число ядер и более) говорят о чрезмерной нагрузке на систему и потенциальных проблемах с производительностью.

В классическом Unix LA имеет смысл среднего количества процессов в очереди на исполнение + количества выполняемых процессов за единицу времени. Т.е. LA == 1 означает, что в системе считается один процесс, LA > 1 определяет сколько процессов не смогли стартовать, поскольку им не хватило кванта времени, а LA < 1 означает, что в системе есть незагруженные ядра.

В Linux к к количеству процессов добавили ещё и процессы, ожидающих ресурсы. Теперь на рост LA значительно влияют проблемы ввода/вывода, такие как недостаточная пропускная способность сети или медленные диски.

LA усредняется по следующей формуле LAt+1=(LAcur+LAt)/2. Где LAt+1 — отображаемое значение в момент t+1, LAcur — текущее измеренное значение, LAt — значение отображавшееся в момент t. Таким образом сглаживаются пики и после резкого падения нагрузки значение LA будет медленно снижаться, а кратковременный пик нагрузки будет отображен половинной величиной LA.

PID

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

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

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

C

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

#include <unistd.h>
pid_t getpid(void);

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

#include <stdio.h>
#include <unistd.h>
 
int main() {
    pid_t p = getpid();
    printf("My PID is %d\n", p);
    return ;
}

Как просматривать запущенные процессы в Linux top

Самый простой способ узнать, какие процессы запущены на сервере в данный момент, — использовать команду top:

top

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

Можно увидеть, что 1 процесс запущен, а 55 процессов  находятся в режиме ожидания (иначе говоря, простаивают, не используя ресурсы процессора).

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

htop

Усовершенствованная версия команды top под названием htop доступна в хранилищах. Чтобы установить ее, используйте данную  команду:

sudo apt-get install htop

Примечание — Для установки htop на centos необходимо использовать следующие команды:

yum install epel-release

После установки репозитория Epel установим htop:

yum install htop

Запустив команду htop, можно увидеть более удобное для пользователя отображение информации:

htop

PID

Каждый процесс имеет уникальный на данный момент времени идентификатор PID. Поменять PID процесса невозможно.

Значения PID 0 и 1 зарезервированы. Процесс с PID==0 не используется, PID==1 — принадлежит программе .

Максимальное значение PID в Linux равняется PID_MAX-1. Текущее значение PID_MAX можно посмотреть командой:

По умолчанию это 2^16 (32768) однако в 64-разрядных Linux его можно увеличить до 2^22 (4194304):

назначаются последовательно. При создании нового процесса вызовом ищется , больший по значению, чем тот, который был возвращён предыдущим вызовом . Если при поиске достигнуто значение , то поиск продолжается с PID=2. Такое поведение выбрано потому, что некоторые программы могут проверять завершение процесса по существованию его PID. В этой ситуации желательно, чтобы PID не использовался некоторое время после завершения процесса.

Команда ps в Linux

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

$ ps опции

$ ps опции | grep параметр

Во втором варианте мы используем утилиту grep для того, чтобы отобрать нужные нам процессы по определенному критерию. Теперь рассмотрим опции утилиты. Они делятся на два типа — те, которые идут с дефисом Unix и те, которые используются без дефиса — BSD. Лучше пользоваться только опциями Unix, но мы рассмотрим и одни и другие. Заметьте, что при использовании опций BSD, вывод утилиты будет организован в BSD стиле.

  • -A, -e, (a) — выбрать все процессы;
  • -a — выбрать все процессы, кроме фоновых;
  • -d, (g) — выбрать все процессы, даже фоновые, кроме процессов сессий;
  • -N — выбрать все процессы кроме указанных;
  • -С — выбирать процессы по имени команды;
  • -G — выбрать процессы по ID группы;
  • -p, (p) — выбрать процессы PID;
  • —ppid — выбрать процессы по PID родительского процесса;
  • -s — выбрать процессы по ID сессии;
  • -t, (t) — выбрать процессы по tty;
  • -u, (U) — выбрать процессы пользователя.

Опции форматирования:

  • -с — отображать информацию планировщика;
  • -f — вывести максимум доступных данных, например, количество потоков;
  • -F — аналогично -f, только выводит ещё больше данных;
  • -l — длинный формат вывода;
  • -j, (j) — вывести процессы в стиле Jobs, минимум информации;
  • -M, (Z) — добавить информацию о безопасности;
  • -o, (o) — позволяет определить свой формат вывода;
  • —sort, (k) — выполнять сортировку по указанной колонке;
  • -L, (H)- отображать потоки процессов в колонках LWP и NLWP;
  • -m, (m) — вывести потоки после процесса;
  • -V, (V) — вывести информацию о версии;
  • -H — отображать дерево процессов;

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

Все процессы, кроме лидеров групп, в том же режиме отображения:

Все процессы, включая фоновые и лидеры групп:

Чтобы вывести больше информации о процессах используйте опцию -f:

При использовании опции -f команда выдает такие колонки:

  • UID — пользователь, от имени которого запущен процесс;
  • PID — идентификатор процесса;
  • PPID — идентификатор родительского процесса;
  • C — процент времени CPU, используемого процессом;
  • STIME — время запуска процесса;
  • TTY — терминал, из которого запущен процесс;
  • TIME — общее время процессора, затраченное на выполнение процессора;
  • CMD — команда запуска процессора;
  • LWP — показывает потоки процессора;
  • PRI — приоритет процесса.

Например, также можно вывести подробную информацию обо всех процессах:

Больше информации можно получить, использовав опцию -F:

Эта опция добавляет такие колонки:

  • SZ — это размер процесса в памяти;
  • RSS — реальный размер процесса в памяти;
  • PSR — ядро процессора, на котором выполняется процесс.

Если вы хотите получить еще больше информации, используйте вместо -f опцию -l:

Эта опция добавляет отображение таких колонок:

  • F — флаги, ассоциированные с этим процессом;
  • S — состояние процесса;
  • PRI — приоритет процесса в планировщике ядра Linux;
  • NI — рекомендованный приоритет процесса, можно менять;
  • ADDR — адрес процесса в памяти;
  • WCHAN — название функции ядра, из-за которой процесс находится в режиме ожидания.

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

С помощью опции -H можно отобразить дерево процессов:

Если вас интересует информация только об определенном процессе, то вы можете использовать опцию -p и указать PID процесса:

Через запятую можно указать несколько PID:

Опция -С позволяет фильтровать процессы по имени, например, выберем только процессы chrome:

Дальше можно использовать опцию -L чтобы отобразить информацию о процессах:

Очень интересно то, с помощью опции -o можно настроить форматирование вывода, например, вы можете вывести только pid процесса и команду:

Вы можете выбрать такие колонки для отображения: pcpu, pmem, args, comm, cputime, pid, gid, lwp, rss, start, user, vsize, priority. Для удобства просмотра можно отсортировать вывод программы по нужной колонке, например, просмотр процессов, которые используют больше всего памяти:

Или по проценту загрузки cpu:

Ещё одна опция — -M, которая позволяет вывести информацию про права безопасности и флаги SELinux для процессов:

Общее количество запущенных процессов Linux можно узнать командой:

Мы рассмотрели все основные возможности утилиты ps. Дальше вы можете поэкспериментировать с её параметрами и опциями чтобы найти нужные комбинации, также можно попытаться применить опции BSD.

Кто использовал файл в Linux

Узнать процесс, который сейчас занимает файл, достаточно просто. Но как узнать, какой процесс обращается к файлу не надолго, например, выполняет его как программу или читает оттуда данные? Эта задача уже труднее, но вполне решаема с помощью подсистемы ядра auditd. В CentOS набор программ для работы с этой подсистемой поставляется по умолчанию, в Ubuntu же его придётся установить командой:

Теперь создаём правило для мониторинга. Например, отследим, кто запускает утилиту who:

Здесь -w — адрес файла, который мы будем отслеживать, -p — действие, которое нужно отслеживать, -k — произвольное имя для правила. В качестве действия могут использоваться такие варианты:

  • x — выполнение;
  • w — запись;
  • r — чтение;
  • a — изменение атрибутов.

Теперь выполним один раз who и посмотрим, что происходит в логе с помощью команды ausearch:

Здесь в секции SYSCALL есть PID процесса, под которым была запущена программа, а также PPID — программа, которая запустила нашу who. Копируем этот PID и смотрим информацию о нём с помощью ps:

Становиться понятно, что это bash.

Демоны


Схематическое изображение демона Максвелла

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

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

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

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

Специальная функция daemon()

Есть нестандартная функция daemon() (её нет в стандарте POSIX, но она реализована в Linux, BSD и др.).

#include <unistd.h>
 
int daemon(int nochdir, int noclose);

Эта функция:

  • делает один fork,
  • сменяет текущий каталог на / (опционально),
  • переоткрывает стандартные дескрипторы потоков ввода-вывода 0, 1, 2 на /dev/null (опционально).

Переоткрывать дескрипторы на /dev/null может быть лучше, чем просто закрывать их. Потому что, если вы впоследствии откроете какой-то файл, лог и пр., новый дескриптор примет одно из стандартных значений, и какая-то библиотека, которая пишет в stderr, может внезапно записать в ваш файл, имеющий дескриптор 2.

Технология двойного fork()

Включает последовательность вызовов fork(), setsid(), fork(). Иначе эту технику можно назвать fork-decouple-fork.

if (fork()) exit();
setsid();
if (fork()) exit();

Зачем это нужно? Такой трюк позволяет убедиться, что процесс демона не является лидером сессии.

Первый процесс в группе является лидером группы. Первый процесс сессии является лидером сессии. Каждая сессия имеет некоторый TTY, ассоциированный с ней. Только лидер сессии может взять контроль над TTY. Для настоящей демонизации (выполнения в фоне) мы должны убедиться, что лидер сессии убит, так что у него точно нет возможности взять контроль над TTY.

Рассмотрим более подробный пример:

#include <time.h>
#include <stdio.h>
#include <unistd.h>
 
#define LOG_PATH "log.txt"
 
void Log(const char* msg) {
    time_t ltime;
    struct tm result;
    char stime32;
 
    ltime = time(NULL);
    localtime_r(&ltime, &result);
    strftime(stime, sizeof(stime), "%F %T", &result);
 
    FILE* f = fopen(LOG_PATH, "a");
    if (!f) {
        return;
    }
    fprintf(f, " %-10s -- PID: %d, PPID: %d, GID: %d, SID: %d\n",
        stime, msg, getpid(), getppid(), getpgid(), getsid());
    fclose(f);
}
 
int main() {
    Log("parent");
 
    pid_t pid = fork();
    if (pid == -1) {
        perror("fork1");
        return 1;
    }
    if (pid > ) {
	// parent
        return ;
    }
    Log("fork #1");
 
    // set new session
    pid_t sid = setsid();
    if (sid == -1) {
        perror("setsid");
        return 1;
    }
    Log("decouple");
 
    pid = fork();
    if (pid == -1) {
        perror("fork2");
        return 1;
    }
    if (pid > ) {
        // parent
        return ;
    }
    Log("fork #2");
 
    while (1) {
        sleep(1);
        Log("daemon");
    }
    return ; 
}

Вывод такой:

 parent     -- PID: 5037, PPID: 3366, GID: 5037, SID: 3366
 fork #1    -- PID: 5038, PPID: 1070, GID: 5037, SID: 3366
 decouple   -- PID: 5038, PPID: 1070, GID: 5038, SID: 5038
 fork #2    -- PID: 5039, PPID: 1070, GID: 5038, SID: 5038
 daemon     -- PID: 5039, PPID: 1070, GID: 5038, SID: 5038
 daemon     -- PID: 5039, PPID: 1070, GID: 5038, SID: 5038
 daemon     -- PID: 5039, PPID: 1070, GID: 5038, SID: 5038
 daemon     -- PID: 5039, PPID: 1070, GID: 5038, SID: 5038

Обратите внимание, что после decouple процесс является лидером сессии, потому что PID = SID. Он по-прежнему может управлять TTY.. Далее обратите внимание, что после fork #2 PID != SID

Теперь процесс не сможет получить управление TTY и стал настоящим демоном.

Далее обратите внимание, что после fork #2 PID != SID. Теперь процесс не сможет получить управление TTY и стал настоящим демоном.

Системные вызовы

Системный вызов (англ. system call) — обращение прикладной программы к ядру операционной системы для выполнения какой-либо операции.

В Unix, Unix-like и других POSIX-совместимых операционных системах популярными системными вызовами являются open, read, write, close, wait, exec, fork, exit и kill. Многие современные ОС имеют сотни системных вызовов. Например, Linux и OpenBSD каждые имеют порядка 380 разных вызовов.

Реализация архитектурно-зависима. Типичный способ — программное прерывание. На x86 есть лучшие способы, например инструкции SYSCALL/SYSRET и SYSENTER/SYSEXIT (используются в Linux начиная с 2.5).

strace

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

Отслеживание активных процессов

Существует несколько различных инструментов для просмотра/перечисления запущенных в системе процессов. Двумя традиционными и хорошо известными из них являются команды ps и top:

Команда ps

Отображает информацию об активных процессах в системе, как показано на следующем скриншоте:

Для получения дополнительной информации о процессах, запущенных текущим пользователем, применяется опция :

Столбцы, присутствующие в выводе команды , имеют следующие значения:

   UID — идентификатор пользователя, которому принадлежит процесс (тот, от чьего имени происходит выполнение).

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

   PPID — идентификатор родительского процесса.

   C — загрузка CPU процессом.

   STIME — время начала выполнения процесса.

   TTY — тип терминала, связанного с процессом.

   TIME — количество процессорного времени, потраченного на выполнение процесса.

   CMD — команда, запустившая этот процесс.

Также можно отобразить информацию по конкретному процессу, используя команду , например:

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

    — показывает информацию о процессах по всем пользователям;

    — показывает информацию о процессах без терминалов;

    — показывает дополнительную информацию о процессе по заданному UID или имени пользователя;

    — отображение расширенной информации.

Если вы хотите вывести вообще всю информацию по всем процессам системы, то используйте команду :

Обратите внимание на выделенный заголовок. Команда поддерживает функцию сортировки процессов по соответствующим столбцам

Например, чтобы отсортировать список процессов по потреблению ресурсов процессора (в порядке возрастания), введите команду:

Результат:

Если вы ходите выполнить сортировку по потреблению памяти (в порядке убывания), то добавьте к имени интересующего столбца знак минуса:

Результат:

Еще один очень популярный пример использования команды — это объединение её и для поиска заданного процесса по его имени:

Результат:

Команда top

Команда top отображает информацию о запущенных процессах в режиме реального времени:

Рассмотрим детально:

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

   USER — пользователь, которому принадлежит процесс.

   PR — приоритет процесса на уровне ядра.

   NI — приоритет выполнения процесса от до .

   VIRT — общий объем (в килобайтах) виртуальной памяти (физическая память самого процесса; загруженные с диска файлы библиотек; память, совместно используемая с другими процессами и т.п.), используемой задачей в данный момент.

   RES — текущий объем (в килобайтах) физической памяти процесса.

   SHR — объем совместно используемой с другими процессами памяти.

   S (сокр. от «STATUS») — состояние процесса:

   S (сокр. от «Sleeping») — прерываемое ожидание. Процесс ждет наступления события.

   I (сокр. от «Idle») — процесс бездействует.

   R (сокр. от «Running») — процесс выполняется (или поставлен в очередь на выполнение).

   Z (сокр. от «Zombie») — зомби-процесс.

   %CPU — процент используемых ресурсов процессора.

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

   TIME+ — количество процессорного времени, потраченного на выполнение процесса.

   COMMAND — имя процесса (команды).

Также в сочетании с основными символами состояния процесса (S от «STATUS») вы можете встретить и дополнительные:

    — процесс с высоким приоритетом;

    — процесс с низким приоритетом;

    — многопоточный процесс;

    — фоновый процесс;

    — лидер сессии.

Примечание: Все процессы объединены в сессии. Процессы, принадлежащие к одной сессии, определяются общим идентификатором сессии — идентификатором процесса, который создал эту сессию. Лидер сессии — это процесс, идентификатор сессии которого совпадает с его идентификаторами процесса и группы процессов.

Команда glances

Команда glances — это относительно новый инструмент мониторинга системы с расширенными функциями:

Примечание: Если в вашей системе отсутствует данная утилита, то установить её можно с помощью следующих команд:

RHEL/CentOS/Fedora

Debian/Ubuntu/Linux Mint

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

ps

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

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

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

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

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

$ ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.0  35660  3396 ?        Ss   авг.26   0:43 /sbin/init
...
$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 21:27 ?        00:00:01 /sbin/init splash

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

sobols@sobols-VirtualBox:~$ ps -p 1 -o comm=
systemd
sobols@sobols-VirtualBox:~$ ps -p 1 -o command=
/sbin/init splash

pgrep

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

$ pgrep 'bash'

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

$ ps ax | awk '{sub(/.*\//, "", $5)} $5 ~ /bash/ {print $1}'

pidof

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

sobols@sobols-VirtualBox:~$ pgrep init
sobols@sobols-VirtualBox:~$ pgrep systemd -l
1 systemd
201 systemd-journal
243 systemd-udevd
673 systemd-logind
1084 systemd
sobols@sobols-VirtualBox:~$ pgrep ^systemd$ -l
1 systemd
1084 systemd
sobols@sobols-VirtualBox:~$ pidof systemd
1084
sobols@sobols-VirtualBox:~$ pidof init
1

top

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

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

watch ps ax --sort=-pcpu

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

htop

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

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

atop

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

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

Сигналы

Сигналы являются одним из способов взаимодействия между процессами (IPC, inter-process communication) в Unix-системах. Фактически, сигнал — это асинхронное уведомление процесса или отдельного потока о каком-либо событии.

Механизм сигналов был изобретён в 1970-х в Bell Labs.

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

Названия сигналов «SIG…» являются числовыми константами (макроопределениями Си) со значениями, определяемыми в заголовочном файле . Числовые значения сигналов могут меняться от системы к системе, хотя основная их часть имеет в разных системах одни и те же значения. Утилита позволяет задавать сигнал как числом, так и символьным обозначением.

Сигналы посылаются:

Сигналы не могут быть посланы завершившемуся процессу, находящемуся в состоянии «зомби».

Обработка сигналов

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

Безопасность

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

Опасность написания обработчика

Распространено мнение, что обработчик сигнала — это сложно и ничего в нем делать не надо.

Обработчик сигнала — это не какая-то неведомая сущность, которая может всё нестандартным образом испортить и из нее физически можно вызывать только малый набор функций. Обработчик сигнала — обычная функция, которая может выполнять все те же действия, что и другой код, которая работает в userspace, как и другой код. Единственные отличия:

  • функция вызывается через обёртку, которая может например поменять стек (если это задано специальным параметром) и может завершить программу при выходе из обработчика сигнала;
  • функция может вызываться в почти произвольных местах кода.

Первая особенность практически никак не влияет, вторая особенность влечет за собой побочные эффекты:

  • вызывая некоторые функции из сигнала, которые работают в многопоточном режиме, мы можем попасть в deadlock, так как попали в обработчик сигнала из критической секции этой самой функции;
  • в однопоточном коде мы можем нарваться на структуры данных в неконсистентном состоянии, если попали в обработчик сигнала из кода, который работает с этими структурами;
  • некоторые библиотечные функции небезопасно вызывать, так как их выполнение тоже может прерываться обработчиком сигнала и они не reentrant. Есть гарантированный список POSIX-функций, которые безопасно вызывать в обработчике сигнала async-signal-safe (табличка в POSIX 2.4.3 Signal Actions). Функций вообще говоря не мало, например fork, exec, mkdir, open, write, connect, sigsuspend и прочие нетривиальные действия. Библиотечные функции sigprocmask, alarm, raise являются async-signal-safe. Такие функции, как malloc, free, запись в лог, обычно многопоточны, и здесь возможен deadlock.

Ещё надо понимать, что обработчик сигнала может быть вызван из состояния, когда уже всё нестандартным образом испорчено. Например, после «проезда по памяти», когда данные произвольным образом повреждены.

1.2. Базовые приемы управления процессами

1.2.1. Переменные командной оболочки $$ и $PPID

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

Ниже приведен пример использования утилиты для вывода значений и .

$ echo $$ $PPID
4224 4223

1.2.2. Утилита pidof

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

root@rhel53 ~# pidof mingetty
2819 2798 2797 2796 2795 2794

1.2.3. Родительские и дочерние процессы

Иерархия процессов системы строится на отношении . Каждый процесс в системе имеет родительский процесс.

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

$ bash
$ echo $$ $PPID
4812 4224

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

$ echo $$ $PPID
4812 4224
$ exit
exit
$ echo $$ $PPID
4224 4223
$

1.2.4. Системные вызовы fork и exec

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

$ echo $$
4224
$ bash
$ echo $$ $PPID
5310 4224
$

1.2.5. Команда exec

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

$ echo $$
4224 # PID процесса bash
$ ksh
$ echo $$ $PPID
5343 4224 # PID процессов ksh и bash
$ exec bash
$ echo $$ $PPID
5343 4224 # PID процессов bash и bash
$ exit
exit
$ echo $$
4224

1.2.6. Утилита ps

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

$ echo $$ $PPID
4224 4223
$ bash
$ echo $$ $PPID
4866 4224
$ bash
$ echo $$ $PPID
4884 4866
$ ps fx
 PID TTY      STAT   TIME COMMAND
4223 ?        S      0:01 sshd: paul@pts/0 
4224 pts/0    Ss     0:00  \_ -bash
4866 pts/0    S      0:00      \_ bash
4884 pts/0    S      0:00          \_ bash
4902 pts/0    R+     0:00              \_ ps fx
$ exit
exit
$ ps fx
 PID TTY      STAT   TIME COMMAND
4223 ?        S      0:01 sshd: paul@pts/0 
4224 pts/0    Ss     0:00  \_ -bash
4866 pts/0    S      0:00      \_ bash
4903 pts/0    R+     0:00          \_ ps fx
$ exit
exit
$ ps fx
 PID TTY      STAT   TIME COMMAND
4223 ?        S      0:01 sshd: paul@pts/0 
4224 pts/0    Ss     0:00  \_ -bash
4904 pts/0    R+     0:00      \_ ps fx
$ 

В Linux обычно используется команда . В Solaris же чаще всего используется команда (которая также работает в Linux). Ниже приведен фрагмент вывода команды .

$ ps fax
 PID TTY      STAT   TIME COMMAND
   1 ?        S      0:00 init 

...

3713 ?        Ss     0:00 /usr/sbin/sshd
5042 ?        Ss     0:00  \_ sshd: paul 
5044 ?        S      0:00      \_ sshd: paul@pts/1 
5045 pts/1    Ss     0:00           \_ -bash
5077 pts/1    R+     0:00               \_ ps fax

1.2.7. Утилита pgrep

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

$ sleep 1000 &
 32558
$ pgrep sleep
32558
$ ps -C sleep
  PID TTY          TIME CMD
32558 pts/3    00:00:00 sleep

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

paul@laika:~$ pgrep -l sleep
9661 sleep

1.2.8. Утилита top

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

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

Что такое команда nohup?

Nohup можно рассматривать как обертку. Префикс вашей команды с nohup:

nohup COMMAND ARGS ....

Цель Nohup в том чтобы перехватить и предотвратить SIGHUP сигналы от достижения команды.

Когда вы префиксируете свою команду nohup, ввод будет перенаправлен из нечитаемого файла ( nohup COMMAND </dev/null ). Проще говоря, не вызывайте команду с nohup, если вам нужно отправить входные данные для этой команды. Когда вы запускаете команду Nohup, он должен быть в состоянии работать без присмотра.

Nohup сначала попытается перенаправить вывод в ./nohup.out или отправит его в ~/nohup.out, если это будет необходимо. Вы также можете решить, куда перенаправить вывод следующим образом:

nohup COMMANDS >/path/to/output/file

О nohup говорить особо нечего, у него нет длинного списка опций. Есть только –help и –version.

1.4. Практическое задание: вводная информация об управлении процессами

1. Используйте утилиту для поиска информации о процессе с именем .

2. Каков с именем ?

3. Используйте команду для установления имени пользователя, под которым вы работаете с терминалом.

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

5. Каков вашей командной оболочки?

6. Каков вашей командной оболочки?

7. Запустите в фоновом режиме два экземпляра процесса с помощью команд .

8. Определите с именем .

9. Выведите информацию только о двух запущенных ранее процессах с помощью утилиты top. После этого завершите работу утилиты .

10. Используйте для уничтожения одного из двух созданных ранее процессов с именами .

11. Используйте одну команду для уничтожения всех процессов с именем .

Запуск программы

В оперативной памяти процесса находятся код и данные, загруженные из файла. При запуске программы из командной строки, обычно создается новый процесс и в его память загружается файл с программой. Загрузка файла делается вызовом одной из функций семейства exec (см. ). Функции отличаются способом передачи параметров, а также тем, используется ли переменная окружения PATH для поиска исполняемого файла. Например execl в качестве первого параметра принимает имя исполняемого файла, вторым и последующими – строки аргументы, передаваемые в argv[], и, наконец, последний параметр должен быть NULL, он дает процедуре возможность определить, что параметров больше нет.

Пример с двумя ошибками:

Ошибка 1:
Первый аргумент передаваемый программе это имя самой программы. В данном примере в списке процессов будет видна программа с именем -l, запущенная без параметров.

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

Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Мой редактор ОС
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: