Исследуем процессы FreeBSD. Часть 1

Dru Lavigne
перевод Станислава Лапшанского
Впервые опубликован: http://www.computerra.ru.

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

Как любая другая UNIX-система, FreeBSD является многозадачной, многопользовательской операционной системой. Это значит, что несколько пользователей могут выполнять несколько программ одновременно. Ядро системы отвечает за то, что каждая из этих программ гарантированно получит процессорное время, и что каждый пользователь увидит верные результаты, выданные этими программами.

Когда вы запускаете программу, она загружается в оперативную память, и после этого ее называют процессом, так как ее инструкции требуют обработки (процесса) процессором. Для того, что бы ядро могло разобраться какой пользователь запускал какие программы, каждому процессу присваивается идентификатор ID (иначе PID - process ID). Обычно PID ассоциируется с, и имеет такие же права, как пользователь, который запустил программу и как группа к которой принадлежит этот пользователь.

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

Когда вы установили FreeBSD, для вас была создана файловая система процессов (procfs). Если вы напечатаете:
$ more /etc/fstab

среди прочего, вы должны будете увидеть следующие строки:
# Device Mountpoint FStype Options Dump Pass#
proc /proc procfs rw 0 0

Когда вы просматриваете информацию о свободном пространстве на ваших дисках, вы можете заметить, что эта файловая система всегда заполнена на 100%:
$ df

Filesystem Size Used Avail Capacity Mounted on
procfs 4.0K 4.0K 0B 100% /proc

Это нормально, так как файловая система процессов не предназначена для хранения файлов, создаваемых пользователями. Эта файловая система используется командами ps и w для получения информации о запущенных процессах. Обратите внимание, что файловая система процессов смонтирована в каталоге /proc. Давайте поглядим на содержимое /proc используя команду ls с ключом C для сортировки вывода по столбцам и с ключом F для печати каталогов со слэшем (/):
$ cd /proc
$ ls -CF
./ 175/ 2072/ 301/ 315/
../ 176/ 227/ 307/ 316/
0/ 177/ 261/ 308/ 317/
1/ 178/ 27/ 309/ 318/
110/ 181/ 273/ 310/ 319/
163/ 197/ 290/ 311/ 320/
166/ 199/ 292/ 312/ 4/
171/ 2/ 3/ 313/ 5/
173/ 202/ 30/ 314/ curproc@

Заметьте, что каждая запись, кроме одной, это каталог с именем состоящим из цифр. Эти числа соответствуют идентификаторам PID запущенных процессов. Последняя запись, curproc, это символьная ссылка, поскольку она заканчивается знаком @. Для того что бы понять на какой файл указывает эта ссылка, напечатайте:
$ file curproc
curproc: symbolic link to 2072

Это означает, что ссылка curproc указывает на какой-то процесс. Если вы напишете:
$ man 5 procfs

вы сможете прочитать, что на самом деле curproc указывает на текущий процесс, который обращается к системе /proc. Таким образом моя команда ls имела идентификатор PID равный 2072.

Теперь давайте посмотрим какая информация хранится о каждом запущенном процессе, путем просмотра содержимого одного из этих каталогов:
$ ls -CF 197
./ ctl file@ mem regs
../ dbregs fpregs note rlimit
cmdline etype map notepg status

Все записи - это обычные файлы, исключая символьную ссылку с именем file. Однако мы совершенно не представляем себе какие данные содержат эти файлы. Попробуем узнать:
$ file *
cmdline: empty
ctl: empty
dbregs: MS Windows COFF Unknown CPU
etype: empty
file: symbolic link to /usr/sbin/inetd
fpregs: data
map: empty
mem: empty
note: empty
notepg: empty
regs: data
rlimit: empty
status: empty

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

Начнем с команды w:
$ whatis w
w(1) - display who is logged in and what they are doing
w(1) - показывает кто сейчас находится в системе и что они делают

$ w
10:43AM up 17:50, 4 users, load averages: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE WHAT
genisis v0 - 9:46AM - w
genisis v1 - Sat04PM 2:02 -csh (csh)
genisis v2 - Sat08PM - -csh (csh)
genisis v3 - Sat05PM 2:02 -csh (csh)

Первая строка показывает текущее системное время, затем время непрерывной работы вашей системы с последней перезагрузки, количество пользователей, в данный момент находящихся в системе и среднее количество заданий в очереди на обработку за 1, 5, 15 последних минут.

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

Если мы воспользуемся командой w с ключом d, то мы получим немного отличающийся вывод, поскольку w будет показывать все процессы которые пользователь выполняет с его терминала:
$w -d
10:55AM up 18:02, 4 users, load averages: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE WHAT
2100 -csh (csh)
2104 su (csh)
2235 w -d
genisis v0 - 9:46AM - w -d
313 -csh (csh)
genisis v1 - Sat04PM 2:14 -csh (csh)
314 -csh (csh)
genisis v2 - Sat08PM - -csh (csh)
315 -csh (csh)
genisis v3 - Sat05PM 2:14 -csh (csh)

Числа над названием терминала это идентификаторы PID процессов. Если вы прочитаете страницу руководства по команде w, то вы узнаете, что это отличная утилита для того что бы быстро посмотреть кто сейчас, и с каких терминалов, находится в системе и что они делают. Однако она не предназначена для детального выяснения информации о процессах, так как это работа утилиты ps. Если вы просто напишете:
$ ps

вы получите базовую информацию о процессах, которые вы запустили, примерно вот так:
PID TT STAT TIME COMMAND
2100 v0 Ss 0:00.13 -csh (csh)
2286 v0 R+ 0:00.00 ps
313 v1 Is+ 0:00.13 -csh (csh)
314 v2 Is+ 0:00.21 -csh (csh)
315 v3 Is 0:00.12 -csh (csh)

Если читать выдачу слева направо, то команда ps показывает PID, название и тип терминала, состояние, затраченное процессорное время (суммируя системное и пользовательское время) и ассоциированную команду, для процессов, которые запущены пользователем выполняющим команду ps.

Состояние - это новый термин, который предоставляет различную информацию о запущенном процессе. При чтении столбца состояния (STAT), первая буква показывает текущий режим выполнения процесса. Возможные значения этой буквы:

D - процесс находится в ожидании дисковой (или короче, непрерываемой) операции
I - процесс в ожидающем режиме (процесс "спит" более 20 секунд)
J - процесс в "тюрьме" (см. man 2 jail - прим. переводчика)
R - процесс выполняется
S - процесс "спит" менее 20 секунд
T - процесс остановлен
Z - мертвый (зомби) процесс

Итак у меня выполняется один процесс (сама команда ps), одна оболочка csh, которая ничего не делала последние 20 секунд и три оболочки, которые ничего не делают более 20 секунд. Символ + показывает что три моих процесса выполняются на переднем плане (foreground-процессы), s говорит о том, что четыре моих процесса являются начальными в сеансе. Не беспокойтесь, если некоторая информация о состоянии процесса не представляется вам важной, действительно, если вы не программист, то некоторая ее часть не будет вам нужна.

Имейте в виду, что команда ps без ключей, по умолчанию покажет вам только ваши процессы, для того что бы посмотреть процессы всех пользователей запущенные на вашем компьютере, используйте ключ a:
$ ps -a
PID TT STAT TIME COMMAND
2100 v0 Ss 0:00.18 -csh (csh)
2403 v0 R+ 0:00.00 ps -a
313 v1 Is+ 0:00.13 -csh (csh)
314 v2 Is+ 0:00.25 -csh (csh)
315 v3 Is+ 0:00.12 -csh (csh)
316 v4 Is+ 0:00.01 /usr/libexec/getty Pc ttyv4
317 v5 Is+ 0:00.01 /usr/libexec/getty Pc ttyv5
318 v6 Is+ 0:00.01 /usr/libexec/getty Pc ttyv6
319 v7 Is+ 0:00.01 /usr/libexec/getty Pc ttyv7

Вы можете решить, что более удобно видеть какие пользователи запустили какую команду, для этого воспользуйтесь ключом u:
$ ps -au
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
genisis 2404 0.0 0.2 428 244 v0 R+ 12:26PM 0:00.00 ps -au
root 273 0.0 0.4 620 448 con- I+ 4:53PM 0:00.02 /bin/sh /usr/loc
root 292 0.0 0.4 624 452 con- I+ 4:53PM 0:00.01 /bin/sh /usr/loc
genisis 313 0.0 0.8 1328 944 v1 Is+ 4:53PM 0:00.13 -csh (csh)
genisis 314 0.0 0.8 1336 960 v2 Is+ 4:53PM 0:00.25 -csh (csh)
genisis 315 0.0 0.8 1328 944 v3 Is+ 4:53PM 0:00.12 -csh (csh)
root 316 0.0 0.5 920 628 v4 Is+ 4:53PM 0:00.01 /usr/libexec/get
root 317 0.0 0.5 920 628 v5 Is+ 4:53PM 0:00.01 /usr/libexec/get
root 318 0.0 0.5 920 628 v6 Is+ 4:53PM 0:00.01 /usr/libexec/get
root 319 0.0 0.5 920 628 v7 Is+ 4:53PM 0:00.01 /usr/libexec/get
genisis 2100 0.0 0.8 1336 960 v0 Ss 9:46AM 0:00.19 -csh (csh)

Мне показалось, что читать вывод команды ps проще, если я воспользуюсь ключом с, который не выводит путь к командам, а показывает только имя:
$ ps -auc
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
genisis 2414 0.0 0.2 428 244 v0 R+ 12:31PM 0:00.00 ps
root 273 0.0 0.4 620 448 con- I+ 4:53PM 0:00.02 sh
root 292 0.0 0.4 624 452 con- I+ 4:53PM 0:00.01 sh
genisis 313 0.0 0.8 1328 944 v1 Is+ 4:53PM 0:00.13 csh
genisis 314 0.0 0.8 1336 960 v2 Ss+ 4:53PM 0:00.26 csh
genisis 315 0.0 0.8 1328 944 v3 Is+ 4:53PM 0:00.12 csh
root 316 0.0 0.5 920 628 v4 Is+ 4:53PM 0:00.01 getty
root 317 0.0 0.5 920 628 v5 Is+ 4:53PM 0:00.01 getty
root 318 0.0 0.5 920 628 v6 Is+ 4:53PM 0:00.01 getty
root 319 0.0 0.5 920 628 v7 Is+ 4:53PM 0:00.01 getty
genisis 2100 0.0 0.8 1336 960 v0 Ss 9:46AM 0:00.21 csh

Однако, пока мы не видим все процессы, которые запущены на этой машине. Для того что бы посмотреть какие запущены демоны воспользуемся ключом x. Вывод скорее всего будет длинным, поэтому перенаправим его команде more:
$ ps -aucx | more
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
genisis 2417 0.0 0.2 428 244 v0 R+ 12:32PM 0:00.00 ps
root 1 0.0 0.2 532 304 ?? ILs Sat11AM 0:00.06 init
root 2 0.0 0.0 0 0 ?? DL Sat11AM 0:00.11 pagedaemon
root 3 0.0 0.0 0 0 ?? DL Sat11AM 0:00.00 vmdaemon
root 4 0.0 0.0 0 0 ?? DL Sat11AM 0:00.20 bufdaemon
root 5 0.0 0.0 0 0 ?? DL Sat11AM 0:09.53 syncer
root 27 0.0 2.0 70780 2540 ?? ILs Sat11AM 0:00.08 mount_mfs
root 30 0.0 0.1 208 92 ?? Is Sat11AM 0:00.00 adjkerntz
root 110 0.0 0.3 536 368 ?? Is 4:53PM 0:00.03 dhclient
root 163 0.0 0.5 904 608 ?? Ss 4:53PM 0:00.53 syslogd
daemon 166 0.0 0.4 916 556 ?? Is 4:53PM 0:00.01 portmap
root 181 0.0 0.5 263052 576 ?? Is 4:53PM 0:00.00 rpc.statd
root 197 0.0 0.6 1028 764 ?? Is 4:53PM 0:00.02 inetd
root 199 0.0 0.6 956 700 ?? Is 4:53PM 0:00.64 cron
root 202 0.0 1.0 1424 1216 ?? Is 4:53PM 0:00.66 sendmail
root 227 0.0 0.4 876 488 ?? Is 4:53PM 0:00.34 moused
root 273 0.0 0.4 620 448 con- I+ 4:53PM 0:00.02 sh
root 292 0.0 0.4 624 452 con- I+ 4:53PM 0:00.01 sh
genisis 313 0.0 0.8 1328 944 v1 Is+ 4:53PM 0:00.13 csh
genisis 314 0.0 0.8 1336 960 v2 Ss+ 4:53PM 0:00.26 csh
genisis 315 0.0 0.8 1328 944 v3 Is+ 4:53PM 0:00.12 csh
root 316 0.0 0.5 920 628 v4 Is+ 4:53PM 0:00.01 getty
root 317 0.0 0.5 920 628 v5 Is+ 4:53PM 0:00.01 getty
root 318 0.0 0.5 920 628 v6 Is+ 4:53PM 0:00.01 getty
root 319 0.0 0.5 920 628 v7 Is+ 4:53PM 0:00.01 getty
genisis 2100 0.0 0.8 1336 960 v0 Ss 9:46AM 0:00.21 csh
root 2239 0.0 3.6 5012 4512 ?? Ss 10:57AM 0:00.40 perl
root 2240 0.0 3.6 5012 4512 ?? I 10:57AM 0:00.02 perl
root 0 0.0 0.0 0 0 ?? DLs Sat11AM 0:00.06 swapper

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

Вы могли заметить, что состав столбцов вывода расширился, когда мы добавили ключ u, из вновь появившихся, наиболее интересны столбцы %CPU и %MEM. Время от времени вам может понадобиться отсортировать вывод команды ps в порядке уменьшения использования памяти или процессора, а не по идентификаторам. Для сортировки по размеру используемой памяти применяется ключ m, а по используемому процессорному времени - ключ r.
$ ps -m
PID TT STAT TIME COMMAND
314 v2 Ss+ 0:00.28 -csh (csh)
2100 v0 Ss 0:00.27 -csh (csh)
313 v1 Is+ 0:00.14 -csh (csh)
315 v3 Is+ 0:00.12 -csh (csh)
2570 v0 R+ 0:00.00 ps -m

$ ps -r
PID TT STAT TIME COMMAND
313 v1 Is+ 0:00.14 -csh (csh)
314 v2 Ss+ 0:00.28 -csh (csh)
315 v3 Is+ 0:00.12 -csh (csh)
2100 v0 Ss 0:00.27 -csh (csh)
2571 v0 R+ 0:00.00 ps -r

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

Когда вы используете команду ps, вы можете увидеть процессы, о которых никогда раньше не слышали. В этом случае, для того что бы найти страницу руководства, способную пролить свет на тайну, используйте команду whatis. Например, являясь очень любопытным субъектом, я попробовал следующее:
$ whatis init syncer adjkerntz inetd portmap rpc.statd
init(8) - process control initialization
(процесс контролирующий инициализацию)
syncer(4) - filesystem synchronizer kernel process
(процесс ядра синхронизирующий файловую систему)
adjkerntz(8) - adjust local time CMOS clock to reflect time zone
changes and keep current timezone offset for the kernel
(настраивает часы компьютера согласно изменениям часового
пояса, а так же хранит текущее смещение относительно
часового пояса для ядра)
inetd.conf(5), inetd(5) - internet super-server
(интернет-суперсервер)
portmap(8) - RPC program, version to DARPA port mapper
(программа RPC, версия DARPA распределителя портов)
rpc.statd(8) - host status monitoring daemon
(демон мониторинга системы)

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

http://www.onlamp.com/pub/a/bsd/2000/11/15/FreeBSD_Basics.html.

Обновлено: 12.03.2015