Linux ps command

Описание 1 этапа:

Не углубляясь в кучу терминов и определений, данный этап можно описать следующими словами: BIOS из MBR (первые 512 байт диска, выбранного для загрузки) загружает First Boot Loader. FSB находит вторичный загрузчик, используя таблицу разделов, просматривая ее, обнаруживает активный раздел, после обнаружения этого раздела — загружает SSB в оперативную память и запускает его. Для корректной загрузки, активный раздел должен содержать каталог /boot,  который должен находиться в начале диска и содержать Second Stage Boot Loader. В целом, SSB — это программа, которая выводит список вариантов загрузки (меню выбора загрузки операционной системы). Загрузчиком может быть LILO (более старый) или GRUB. Загрузчик берет свои настройки из конфигурационного файла (/etc/lilo.conf — для LILO и /boot/grub/grub.conf или /boot/grub/menu.lst — для GRUB). Существуют и другие версии загрузчиков, такие как syslinux, PXElinux, Isolinux, uBoot, но для наглядности, в статье я затронул только LILO и GRUB. Хочу отметить, что исторически (до появления загрузчиков LILO, GRUB и др. и когда образ ядра занимал объем не боле 1,44 Мб) данного этапа не существовало и загрузка происходила с дискеты без файловой системы, на которую был записан образ ядра Linux, который (образ) содержал в себе MBR, то есть BIOS загружал сразу образ ядра и передавал ему управление.

Basic Usage

Now that we’ve seen the default output, it’s time to see a few of the options in action.

3.1. Listing All Processes

Let’s use the -e flag to print all the processes within the system, not just the ones from the current terminal:

We can also see a more detailed output by using the -f option:

Let’s take a closer look at this example to understand it better. We now have some additional columns:

  • UID – the user id of the process owner
  • PPID – the parent process id (in this particular snippet, rcu_gp was spawned by kthread)
  • C – the CPU utilization in percentage
  • STIME – the start time of the process

Furthermore, when ps can identify the process arguments, it will also print them in the CMD column.

3.2. Simple Filtering

In practice, we’re most likely searching for a particular process by name with the -C option:

Notice that we use the complete process executable name rather than a substring.

Additionally, ps also allows us to filter based on a list of process ids using the -p flag:

We can also search by the user name by specifying it in the -u option:

There is one particular gotcha here, but we’ll explain it in detail in the next section.

Examples

To see every process running on the system, using the standard syntax:

ps -e
ps -ef
ps -eF
ps -ely

To see every process on the system, using BSD syntax:

ps ax
ps axu

To display a process tree:

ps -ejH
ps axjf

To get info about threads:

ps -eLf
ps axms

To get security info:

ps -eo euser,ruser,suser,fuser,f,comm,label
ps axZ
ps -eM

To see every process running as root (real and effective ID) in user format:

ps -U root -u root u

To see every process with a user-defined format:

ps -eo pid,tid,class,rtprio,ni,pri,psr,pcpu,stat,wchan:14,comm
ps axo stat,euid,ruid,tty,tpgid,sess,pgrp,ppid,pid,pcpu,comm
ps -Ao pid,tt,user,fname,tmout,f,wchan

Print only the process IDs of syslogd, the syslog daemon:

ps -C syslogd -o pid=

Print only the name of process ID 15:

ps -p 15 -o comm=

Notes

ps works by reading the virtual files in /proc. ps does not need to be setuid kmem or have any privileges to run. Do not give this ps any special permissions.

This ps needs access to namelist data for proper WCHAN display. For kernels prior to 2.6, the System.map file must be installed.

CPU usage is currently expressed as the percentage of time spent running during the entire lifetime of a process. This is not ideal, and it does not conform to the standards of ps. CPU usage is unlikely to add up to exactly 100%.

The SIZE and RSS fields don’t count some parts of a process including the page tables, kernel stack, struct thread_info, and struct task_struct. This is usually at least 20 KiB of memory that is always resident. SIZE is the virtual size of the process (code+data+stack).

Processes marked <defunct> are dead processes (so-called «zombies») that remain because their parent has not destroyed them properly. These processes will be destroyed by init if the parent process exits.

If the length of the username is greater than the length of the display column, the numeric user ID is displayed instead.

Что такое «Процесс»

В первую очередь разберемся, что это такое — процесс. Выше уже было сказано, что он отвечает за выполнения программы. Это так, но точнее будет сказать, что процесс — это идентификатор программы. Дело в том, что в системе Linux могут работать несколько пользователей, которые запускают одни и те же процессы, а в некоторых случаях даже один пользователь может их открыть. Системе необходимо как-либо идентифицировать это, поэтому существует такое понятие, как PID (Process Identificator).

Вам будет интересно:В Point Blank или Lineage произошла ошибка приложения с номером 726? Есть решение!

В системе любой процесс может выполняться в нескольких режимах:

Запуск. Данный режим означает, что процесс или уже работает, или запускается.
Ожидание. В данном состоянии процесс ждет получения какой-либо команды, соответственно, он не выполняется.
Остановлено. Все просто — процесс был остановлен принудительно пользователем. Чтобы он продолжил свою работу, ему нужно дать соответствующий сигнал.
Мертвый. Он также называется «зомби-процессом». Это когда он был убит пользователем, но все равно отображается в списке. Чаще всего это происходит из-за того, что у него были смежные процессы, которые продолжили свою работу.

Использование системного вызова fork

Системный вызов создает новый процесс. В показан

используемый в простом примере C-кода.

Листинг 2. Простое применение fork(2)
sunbox$ cat fork1.c
#include <unistd.h>
#include <stdio.h>

int main (void) {

        pid_t p; /* fork returns type pid_t */
        p = fork();
        printf("fork returned %d\n",  p);
}

sunbox$ gcc fork1.c -o fork1
sunbox$ ./fork1
fork returned 0
fork returned 698

Код в просто вызывает и отображает целочисленный результат выполения через вызов . Делается только один вызов, но вывод отображается дважды. Это происходит потому, что новый процесс создается в рамках вызова . После вызова возвращаются два отдельных процесса. Это часто называют «вызванный единожды, возвращается дважды.»

Возвращаемые

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

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

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

Листинг 3. Более полный пример использования fork
sunbox$ cat fork2.c
#include <unistd.h>
#include <stdio.h>

int main (void) {

        pid_t p;

        printf("Original program,  pid=%d\n",  getpid());
        p = fork();
        if (p == 0) {
                printf("In child process,  pid=%d,  ppid=%d\n", 
                        getpid(),  getppid());
        } else {
                printf("In parent,  pid=%d,  fork returned=%d\n", 
                        getpid(),  p);
        }
}

sunbox$ gcc fork2.c -o fork2
sunbox$ ./fork2
Original program,  pid=767
In child process,  pid=768,  ppid=767
In parent,  pid=767,  fork returned=768

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

Обратите внимание на то, как потомок находит своего родителя при помощи , и как родитель использует результат для поиска своих потомков

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

— это только половина уравнения. Семейство системных вызовов

запускает определенную программу.

Как отправлять сигналы процессам в Linux

Все процессы в Linux отвечают на сигналы.

Сигналы — способ завершить или изменить поведение программ на уровне ОС.

Как отправлять процессам сигналы при помощи PID

Наиболее распространенным способом передачи сигналов программам является команда kill.

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

kill PID_of_target_process

Это отправит всем процессам сигнал TERM. Данный сигнал приказывает процессу завершиться. Это позволяет программе выполнять операции по очистке и завершить работу без помех.

Если программа неисправна и не завершает работу при отправке сигнала TERM, можно усилить сигнал, передав сигнал KILL:

kill -KILL PID_of_target_process

Данный специальный сигнал отправляется не программе.

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

Каждый сигнал имеет ассоциированный номер, который можно передать вместо имени. К примеру, можно отправить «-15» вместо «-TERM» и «-9» вместо «-KILL».

Как использовать сигналы для других целей

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

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

sudo kill -HUP pid_of_apache

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

Чтобы просмотреть список всех сигналов, которые можно отправить с kill, наберите:

kill -l

Как отправлять сигналы процессам по имени

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

Команда pkill работает почти также, как kill, но она действует от имени процесса:

pkill -9 ping

Команда, приведенная выше, является эквивалентом:

kill -9 `pgrep ping`

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

killall firefox

Вышеуказанная команда отправит сигнал TERM каждому экземпляру firefox, запущенному на данном компьютере.

Как установить приоритеты процессов

Часто возникает необходимость установить, какие процессы имеют приоритет в серверной среде.

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

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

Задачи с высоким приоритетом имеют низшее значение  nice, так как они поглощают ресурсы. С другой стороны, задачи с низким приоритетом имеют высокое значение nice, так как они используют минимальное количество ресурсов.

При запуске команды top в начале статьи был выведен столбец, отмеченный как «NI». В нем указывается значение nice процесса:

top

В зависимости от системы, значение nice может варьироваться от «-19/-20» (наивысший приоритет) до «19/20» (самый низкий приоритет).

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

nice -n 15 command_to_execute

Это работает только при запуске новой программы.

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

renice 0 PID_to_prioritize

Примечание: в то время как nice работает с именем команды, renice вызывает PID процесса.

Описание 2 этапа:

 Второй этап можно характеризовать так: подготовка системы для запуска служб демонов. При подготовке, Загрузчик загружает в память образ ядра из каталога /boot. Давайте рассмотрим пример образа ядра на примере ОС Debian 6:

boot@debian:~# file /boot/vmlinuz-2.6.32-5-686
/boot/vmlinuz-2.6.32-5-686: Linux kernel x86 boot executable bzImage, \
     version 2.6.32-5-686 (unknown@Debian) #, RO-rootFS, swap_dev 0x2, Normal VGA

В приведенном листинге, видно, что команда file выводит информацию о файле образа ядра. В данной информации говориться, что это ядро линукс (Linux kernel), 32-битной архитектуры (x86), содержащий возможность загрузки (boot), исполняемый (executable), в формате bzImage (то есть сжатое, бывают образы не сжатые), далее указывается версия ядра и кое-какие другие параметры образа. Данных файлов может быть несколько (в зависимости от количества установленных версий ядра) и для загрузки выбирается тот, который указан в настройках загрузчика. Образ ядра, инициализирует и подготавливает память, процессор/ы, остальное оборудование, монтирует корневой раздел в режиме только для чтения для загрузки остальной системы (устройство и раздел на котором размещен корень системы должен быть указан в настройках загрузчика GRUB (/boor/grub.conf) или LILO (/boor/lilo.conf)) в виде параметра root=. При этом, выводится сообщение VFS: Mounted root (ext2 filesystem) readonly. Кроме того, ядро из конфигурационного файла загрузчика получает параметры загрузки, такие как корневая файловая система, отображать сообщения ядра или нет и т.п. Параметры, переданные текущему загруженному ядру можно посмотреть в . Вот пример параметров все того же Debian:

boot@debian:~# cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-2.6.32-5-686 root=UUID=6852e86c-b8f1-49d0-b1eb-9d10171083c3 ro quiet

Т.к. ядро Linux является модульным, то при загрузке может возникнуть необходимость подключить модуль ядра, который находится на еще не примонтированной файловой системе. Для решения данной проблемы при загрузке подгружается архив файловой системы (он же инициализационный RAM диск или initrd), содержащий в себе необходимый для загрузки набор модулей ядра. Вот так он выглядит для указанного выше ядра:

root@debian:~# file /boot/initrd.img-2.6.32-5-686
/boot/initrd.img-2.6.32-5-686: gzip compressed data, from Unix, last modified: Thu Mar 17 09:44:39 2011

Какой архив initrd подгружать при загрузке, так же указывается в FSB GRUB или LILO:

boot@debian:~# grep initrd -B4 /boot/grub/menu.lst
title           Debian GNU/Linux, kernel 2.6.26-2-686
root            (hd0,0)
kernel          /boot/vmlinuz-2.6.26-2-686 root=/dev/sda1 ro quiet
initrd          /boot/initrd.img-2.6.26-2-686

Т.к. (вывод сообщений на экран) должен быть связан с каким-либо процессом, соответственно с идентификатором процесса, а у ядра нет идентификатора, оно оно помещает сообщения ядра (и модулей) в буфер кольца ядра и выводит на экран. Данный буфер еще называется dmesg. Его содержимое можно просмотреть, выполнив команду dmesg. После полной инициализации ядро передает управление процеcсу init (первому системному процессу с PID=1). На экран выводится сообщение INIT: version 2.76 booting. При этом, бинарный файл init последовательно ищется в корневом разделе в каталогах: /sbin/init, /etc/init, /bin/init, если в указанных местах не обнаружен файл, то ядро пытается запустить шелл /bin/sh (это, собственно, есть однопользовательский режим загрузки, он же режим восстановления). При этом, не запускается ни один демон. Если не найден и шелл, то вываливается ошибка Kernel panic: No init found. Try passing init= option. Данная ситуация может возникнуть скорее всего, потому что неверно смонтирован корневой раздел.

Маленький итог:

В данной статье я постарался, как можно прозрачней описать процесс запуска операционных систем UNIX, в том виде, в каком я его понял. Некоторые пособия/статьи разделяют загрузку на большее количество этапов. Я постарался изложить так, чтобы прочитав статью, можно было понять процесс загрузки UNIX не вчитываясь в кучу других материалов. Конечно, никто не запрещает углубиться в изучение процесса загрузки ОС, благо в интернете их достаточно. Жду комментариев и дополнений.

Что еще почитать:

upd 2011.01.21: переработано и дополнено описание upd 2011.06.10: дополнено описание upd 2011.06.12: переработка и дополнение всех этапов загрузки, добавление процесса загрузки upstart и ОС BSD.upd 2011.06.27: Дополнение .

Заключение

Как и сама операционная система Linux, процесс загрузки ядра является
чрезвычайно гибким и универсальным и поддерживает большое количество
процессоров и аппаратных платформ. В самом начале загрузчик loadlin
обеспечивал простой способ загрузки Linux без поддержки каких-либо
необязательных аксессуаров. Загрузчик LILO расширил круг поддерживаемых
функций, однако его недостатком являлось отсутствие поддержки файловых
систем. Последнее поколение загрузчиков, таких как GRUB, позволяет
загружать Linux с самых различных файловых систем (начиная с Minix и
заканчивая Reiser).

Похожие темы

  • Оригинал статьи: Inside the Linux boot process (EN).
  • Boot Records Revealed — превосходный ресурс, посвященный MBR
    и различным загрузчикам. На нем не только рассматривается структура
    MBR, но и обсуждаются GRUB, LILO и различные
    Windows-загрузчики.(EN)
  • Обратитесь к странице DiskGeometry, если вы хотите понять диски и их геометрию.
    Здесь вы найдете интересную обзорную информацию по свойствам
    дисков.(EN)
  • live CD —
    это операционная система, которая может загружаться с CD или DVD, без
    использования жесткого диска.(EN)
  • Статья «Boot loader showdown: Getting to know LILO and GRUB» (EN)
    (developerWorks, август 2005 г.) дает детальный обзор возможностей
    загрузчиков LILO и GRUB.
  • В материалах для подготовки к экзамену Linux Professional Institute
    (LPI) — серии учебных материалов в разделе учебных пособий
    developerWorks — содержится детальное введение в загрузку операционной
    системы Linux, а также описывается много других фундаментальных задач
    Linux, которые могут оказаться полезными при подготовке к сертификации
    на системного администратора.
  • Загрузчик LILO был предшественником GRUB, однако и сейчас используется
    для загрузки Linux.(EN)
  • Команда mkintrd используется для создания образа начального
    RAM-диска. Эта команда полезна для создания начальной корневой системы
    для конфигурации загрузчика, обеспечивающей предварительную загрузку
    блочных устройств, необходимых для доступа к действительной корневой
    файловой системе.(EN)
  • На сайте Debian
    Linux Kernel Project вы можете найти дополнительную информацию
    по ядру Linux, загрузке и разработке для встраиваемых
    систем.(EN)
  • Приложение MicroMonitor предоставляет среду для загрузки для большого
    количества компактных устройств. Вы можете использовать его для
    наблюдения за процессом загрузки Linux во встраиваемых приложениях.
    Приложение портировано на процессоры ARM, XScale, MIPS, PowerPC,
    Coldfire и Super-H (Hitachi).(EN)
  • GNU GRUB
    предоставляет оболочку для загрузки, которая поддерживает большое
    количество опций и отличается высокой гибкостью.(EN)
  • LinuxBIOS — это замена BIOS. Это приложение не только
    позволяет загрузить Linux, LinuxBIOS само является сжатым ядром
    Linux.(EN)
  • OpenBIOS — это другой
    проект переносимой BIOS, который способен работать на самых различных
    архитектурах, таких как x86, Alpha и AMD64.(EN)
  • На сайте kernel.org вы
    можете найти самое последнее дерево ядра.(EN)
  • В разделе Linux сайта developerWorks вы найдете множество
    ресурсов для разработчиков Linux.
  • Используйте ознакомительные версии программного обеспечения IBM, которые
    можно загрузить непосредственно с сайта developerWorks, в своем
    следующем проекте для Linux.(EN)
Добавить комментарий

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

Adblock
detector