Досліджуємо процеси. Частина 2

Dru Lavigne

У першій частині статті ми дізналися що представляють з себе процеси, а так само як подивитися список запущених процесів на вашій FreeBSD. У цій частині ми дізнаємося як процеси спілкуються між собою, як ви можете що-небудь передати процесу і навіщо вам це може знадобитися.

Хід спілкування процесів називається межпроцессное взаємодією. Процеси не мають права просто передавати що-небудь кому-небудь. У FreeBSD існує 31 зумовлене повідомлення. Ці повідомлення називаються сигналами. Ви можете подивитися список сигналів набравши:

kill -l

HUP INT QUIT ILL TRAP ABRT EMT FPE KILL
BUS SEGV SYS PIPE ALRM TERM URG STOP TSTP
CONT CHLD TTIN TTOU IO XCPU XFSZ VTALRM
PROF WINCH INFO USR1 USR2

Кожен сигнал має номер, і в цьому списку вони перераховані в порядку номерів. Таким чином HUP = 1, INT = 2 і т.д. Процес може посилати ці сигнали іншим процесам. Користувачі можуть теж саме.

Для того, щоб зрозуміти, що означає кожен з цих сигналів наберіть man 2 sigaction або man 3 signal. Наступна нижче таблиця коротко описує кожен з 31 сигналів, а також результати їх застосування. Оскільки користувачі також можуть посилати будь-які з цих сигналів, поруч з найбільш часто використовуваними сигналами я поставив зірочку.


































































































































































Назва сигналу # Дія за замовчуванням Опис
*HUP 1 знищити процес обірвався зв'язок з терміналом
*INT 2 знищити процес переривання програми
*QUIT 3 створити дамп пам'яті вихід з програми
ILL 4 створити дамп пам'яті заборонена інструкція
TRAP 5 створити дамп пам'яті зневадження переривання
ABRT 6 створити дамп пам'яті виклик функції abort
EMT 7 створити дамп пам'яті була виконана імітованому інструкція
FPE 8 створити дамп пам'яті виняток при операціях з плаваючою точкою
*KILL 9 знищити процес вбити програму
BUS 10 створити дамп пам'яті помилка на шині
SEGV 11 створити дамп пам'яті порушення сегментації
SYS 12 створити дамп пам'яті виклик неіснуючої системної програми
PIPE 13 знищити процес запис у канал при відсутності читання
ALRM 14 знищити процес минув таймер реального часу
*TERM 15 знищити процес програмний сигнал на знищення процесу
URG 16 ігнорування сигналу невідкладне умова
*STOP 17 зупинити процес останов (не може ігноруватися)
*TSTP 18 зупинити процес сигнал стоп з клавіатури
CONT 19 ігнорування сигналу продовжити після зупинки
CHLD 20 ігнорування сигналу статус породженого процесу змінився
TTIN 21 зупинити процес спроба фонового читання
TTOU 22 зупинити процес спроба фонової запису
IO 23 ігнорування сигналу введення / висновок можливий
XCPU 24 знищити процес вичерпано ліміт процесорного часу
XFSZ 25 знищити процес вичерпаний ліміт на розмір файлу
VTALRM 26 знищити процес сигнал від віртуального таймера
PROF 27 знищити процес сигнал від таймера профайлера
WINCH 28 ігнорування сигналу зміна розмірів вікна
INFO 29 ігнорування сигналу запит статусу з клавіатури
USR1 30 знищити процес Певний користувачем сигнал 1
USR2 31 знищити процес Певний користувачем сигнал 2

Деякі з сигналів використовувалися користувачами настільки часто, що отримали свої клавіатурні скорочення. Для перегляду цих скорочень подивіться чотири останні рядки виводу команди stty-e:

stty -e
discard dsusp eof eol eol2 erase intr kill lnext
^O ^Y ^D <undef> <undef> ^H ^C ^U ^V
min quit reprint start status stop susp time werase
1 ^\ ^R ^Q ^T ^S ^Z 0 ^W

Символ «^» означає, що ви повинні натиснути клавішу «ctrl», а потім зазначену за ним літеру. Зверніть увагу, що три сигнали були прив'язані до керуючих послідовностей:

Не плутайте слово «kill» у висновку команди stty з сигналом KILL (сигнал 9). Комбінація ^ U видаляє рядок, а не шле сигнал номер 9. Для того що б у цьому переконатися, надрукуйте в командній оболонці довгий рядок, а потім натисніть ^ U.

Але як послати сигнал, який не має відповідної комбінації клавіш? Використовуйте для цього команду kill.

whatis kill
kill (1) – terminate or signal a process (знищення або сигналізація процесу)
kill (2) – send signal to a process (надіслати сигнал процесу)

Є пара способів використання команди kill. Якщо ви просто надрукуєте:

kill PID

то за замовчуванням процесу з ідентифікатором PID буде посланий сигнал TERM. Якщо ви хочете послати який-небудь інший сигнал, то в команді вкажіть його назву або номер:

kill-названіе_сігнала PID

або

kill-номер_сігнала PID

Таким чином команди

kill PID

kill -TERM PID

kill -15 PID

еквівалентні. Не забувайте, що в UNIX має значення регістр набраних команд, якщо ви надрукуєте:

kill -term PID

то отримаєте наступне повідомлення про помилку:

term: Unknown signal; kill -l lists all signals.

Отже тепер ми знаємо про кожен з 31 можливих повідомлень, а так само можемо посилати їх різним процесам. Давайте розглянемо причини, по яких вам може знадобитися послати процесу сигнал. Коли ви опрацьовує який-небудь питання використовуючи FreeBSD Handbook або інше керівництво, їх автори часто навчають як і що міняти в тих чи інших конфігураційних файлах, а потім говорять вам про необхідність послати сигнал HUP. Справа в тому, що більшість процесів прочитують свої конфігураційні файли тільки при першому запуску. Сигнал HUP говорить процесу, що він повинен припинити виконання. Після того як процес перезапуститься, він перечитає конфігураційні файли та внесені до них зміни набудуть чинності. Аналогічним чином, коли ви виходите командою logout з терміналу, сигнал HUP розсилається всіх процесів, які були запущені на цьому терміналі. Це означає, що всі процеси які виконувалися на цьому терміналі будуть зупинені.

Іноді ви можете запустити процес і захотіти його зупинки, до того, як він завершиться в штатному режимі. Наприклад у пориві натхнення ви можете вирішити, що вам необхідно подивитися імена всіх файлів у вашій системі. Це можна зробити написавши наступне:

find / -print | more

Однак, найімовірніше ви швидко стомитеся натискати пробіл і зрозумієте, що насправді вам зовсім не хочеться в даний момент переглядати список всіх ваших файлів. Іншими словами вам захочеться подати переривають сигнал. Один із шляхів зробити це, натиснути на терміналі «Ctrl + C»:

^C

Те, що на вашому терміналі з'явиться запрошення інтерпретатора команд, свідчить про те, що посланий вами сигнал INT спрацював.

Знову виконайте ту ж саму команду find, але на цей раз пошліть сигнал 3, натиснувши на клавіатурі "Ctrl + \»:

^

Тепер, перед тим, як ви отримаєте запрошення інтерпретатора команд, ви побачите таке повідомлення:

Quit (core dumped)
Вихід (збережено «посмертний» дамп пам'яті)

Якщо ви скористайтеся комбінацією Alt + F1, що б подивитися повідомлення системної консолі, там ви побачите повідомлення приблизно такого змісту:

Nov 19 13:50:09 genisis / kernel: pid 806 (find), uid 1001: exited on signal 3
Nov 19 13:50:09 genisis / kernel: pid 807 (more), uid 1001: exited on signal 3 (core dumped)

Якщо тепер ви повернетеся до попереднього термінал і подивіться список файлів у каталозі, серед іншого ви обов'язково знайдете файл more.core. Зазвичай вам ніколи не буде потрібно посилати процесу сигнал номер 3, якщо звичайно ви не програміст, який знає як використовувати відладчик ядра. Я включив цей приклад у статтю для того що б показати різницю між сигналами 2 і 3. Видаляйте core-файли без побоювання.

Взаємодія між процесами (в оригіналі використовується термін «межпроцессное комунікації» – прим. Перекладача) практично ні чим не відрізняється від будь-яких інших видів комунікацій: ви чи який-небудь процес можете послати сигнал у надії на певний результат, однак процес одержує цей сигнал розпоряджається з ним «на свій розсуд». Пам'ятайте, що процеси – це всього лише запущені програми. Більшість програм використовують процедури «обробки сигналів», застосовувані для того, щоб вирішувати що і як треба робити з поданими сигналами в даний момент часу. Зазвичай, якщо ви посилаєте процесу який-небудь із сигналів зупиняють виконання програми, процедура обробки сигналів цього процесу намагається коректно закрити всі використовувані програмою файли для запобігання втрати даних після зупину. У деяких випадках обробник сигналів може просто проігнорувати надійшов процесу сигнал і відхилити запит на зупинення програми (зазвичай так чинять завислі програми, які на момент надходження сигналу вже не працюють належним чином – прим. перекладача).

Проте (на щастя – прим. Перекладача), деякі сигнали не можуть бути проігноровані програмою. Це наприклад дев'ятий і сімнадцятий сигнали. Уявімо, що ви хочете зупинити процес який ви деякий час тому запустили. Скориставшись зв'язкою команди ps і grep, ви дізналися PID процесу, а потім за допомогою команди kill послали йому сигнал TERM, а потім вирішили перевірити зупинений чи процес повторивши команду ps:

ps | grep processname

kill PID

ps | grep processname

Однак при повторі команди ps ви знову виявили цей процес у списку, а це значить, що з якихось причин сигнал TERM був проігнорований. Будь-яка з цих двох команд виправить ситуацію:

kill -9 PID

або

kill -KILL PID

Якщо ви тепер повторіть команду ps, то ви повинні будете отримати порожній список, що свідчить про успішне останове процесу.

Ви можете запитати: «Чому б завжди не посилати процесам сигнал 9, якщо він не може бути ігнорований?». Справа в тому, що сигнал 9 насправді просто «вбиває» процес, не даючи йому часу на коректне збереження всіх оброблених даних, що означає, що при застосуванні сигналу 9 можуть бути втрачені дані (ніколи не застосовуйте сигнал номер 9 без крайньої на те необхідності – прим. перекладача). Набагато краще спробувати для початку надіслати процесу який-небудь інший сигнал зупинки, а сигнал номер 9 мати «про запас» для процесів вперто ігнорують інші сигнали. Не забувайте також, що якщо ви працюєте від імені звичайного користувача, то ви зможете посилати сигнали тільки процесам, власником яких є. Суперкористувач root може посилати сигнали будь-яким процесам.

Може виникнути ситуація, коли вам захочеться зупинити всі належні вам процеси. Результати цієї дії будуть відрізнятися в залежності від того чи перебуваєте ви в системі як звичайний або як суперкористувач.

Продемонструємо це. Увійдіть в систему на іншому терміналі і введіть команду ps:

ps
PID TT STAT TIME COMMAND
316 v0 Ss 0:00.39 -csh (csh)
957 v0 R+ 0:00.00 ps
317 v1 Is+ 0:00.20 -csh (csh)
915 v2 Is 0:00.12 -csh (csh)
941 v2 I+ 0:00.09 lynx
942 v2 Z+ 0:00.00 (lynx)
913 v3 Is 0:00.12 -csh (csh)
946 v3 I+ 0:00.01 /bin/sh /usr/X11R6/bin/startx
951 v3 I+ 0:00.04 xinit /home/genisis/.xinitrc —
955 v3 S 0:03.00 xfce

У цьому прикладі я увійшов в систему з терміналів 0, 1, 2, 3. Я запустив команду ps з консолі (термінал 0 по сумісництву виконує роль системної консолі – прим. Перекладача), на першому терміналі запущена оболонка командного процесора, на другому – запущений браузер lynx і на третьому у мене запущений сеанс X Window. І так я є власником 10 процесів. Якщо в команді kill я скористаюся ідентифікатором процесу (PID) рівним -1, я відправлю вказаний в команді сигнал всім належним мені процесам. так спробуємо послати сигнал TERM таким чином:

kill -1

А тепер перевіримо результати, скориставшись командою ps:

ps
PID TT STAT TIME COMMAND
316 v0 Ss 0:00.41 -csh (csh)
969 v0 R+ 0:00.00 ps
317 v1 Ss+ 0:00.21 -csh (csh)
915 v2 Is+ 0:00.12 -csh (csh)
913 v3 Is+ 0:00.12 -csh (csh)

Зверніть увагу – ми зупинили шість процесів, проте чотири залишилися проігнорували сигнал TERM. Давайте будемо більш агресивні:

kill -KILL -1

ps
PID TT STAT TIME COMMAND
317 v1 Ss 0:00.22 -csh (csh)
995 v1 R+ 0:00.00 ps

Якщо ви «пройдетеся» по тих чотирьох терміналів, на яких виконувалися ваші програми, то на трьох з них ви побачите запрошення увійти в систему. Остання команда kill знищила всі процеси, за винятком свого батьківського процесу, тобто командного інтерпретатора C shell, в якому ви набрали команду kill (так сталося тому, що структура процесів в UNIX деревоподібна і кожен процес повинен мати свого батька – прим. перекладача).

Зверніть увагу, що якщо ви допустите помилку при наборі команди і напишете:

kill 1

замість

kill -1

то ви отримаєте повідомлення про помилку:

1: Operation not permitted
1: Дія заборонено

Справа в тому, що -1 це спеціальний ідентифікатор процесу, який позначає «всі процеси», а 1 це ідентифікатор процесу з ім'ям init. Тільки root може зупиняти процес init. До того ж суперкористувач повинен зупиняти процес init тільки за умови того, що він знає що робить.

Тепер давайте подивимось що відбудеться, якщо ми повторимо ту ж вправу, але тільки від імені суперкористувача. Для початку на моєму тестовому комп'ютері (де виконуються наступні програми: apache, mysql, squid, nfs тощо) я виконаю команду ps:

ps -acux
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
genisis 1050 0.0 0.2 428 244 v0 R+ 4:08PM 0:00.00 ps
root 1 0.0 0.2 532 304 ?? ILs 5:10AM 0:00.04 init
root 2 0.0 0.0 0 0 ?? DL 5:10AM 0:00.03 pagedaemon
root 3 0.0 0.0 0 0 ?? DL 5:10AM 0:00.00 vmdaemon
root 4 0.0 0.0 0 0 ?? DL 5:10AM 0:00.04 bufdaemon
root 5 0.0 0.0 0 0 ?? DL 5:10AM 0:02.62 syncer
root 27 0.0 2.0 70780 2540 ?? ILs 5:10AM 0:00.08 mount_mfs
root 30 0.0 0.1 208 92 ?? Is 5:10AM 0:00.00 adjkerntz
root 110 0.0 0.3 536 368 ?? Ss 10:10AM 0:00.22 dhclient
root 163 0.0 0.5 904 608 ?? Ss 10:10AM 0:00.19 syslogd
daemon 166 0.0 0.4 916 556 ?? Is 10:10AM 0:00.01 portmap
root 171 0.0 0.3 504 320 ?? Is 10:10AM 0:00.00 mountd
root 173 0.0 0.1 360 172 ?? Is 10:10AM 0:00.01 nfsd
root 175 0.0 0.1 352 164 ?? I 10:10AM 0:00.00 nfsd
root 176 0.0 0.1 352 164 ?? I 10:10AM 0:00.00 nfsd
root 177 0.0 0.1 352 164 ?? I 10:10AM 0:00.00 nfsd
root 178 0.0 0.1 352 164 ?? I 10:10AM 0:00.00 nfsd
root 181 0.0 0.5 263052 576 ?? Is 10:10AM 0:00.00 rpc.statd
root 197 0.0 0.6 1028 764 ?? Is 10:10AM 0:00.02 inetd
root 199 0.0 0.6 956 700 ?? Ss 10:10AM 0:00.19 cron
root 202 0.0 1.0 1424 1216 ?? Is 10:10AM 0:00.20 sendmail
root 227 0.0 0.4 876 488 ?? Is 10:10AM 0:00.00 moused
root 261 0.0 1.4 2068 1704 ?? Ss 10:10AM 0:00.98 httpd
root 275 0.0 0.4 620 448 con- I+ 10:10AM 0:00.02 sh
root 293 0.0 0.4 624 452 con- I+ 10:10AM 0:00.01 sh
mysql 303 0.0 1.4 10896 1796 con- S+ 10:10AM 0:00.43 mysqld
nobody 305 0.0 4.7 6580 5928 con- S+ 10:10AM 0:05.42 squid
nobody 308 0.0 1.4 2092 1704 ?? I 10:10AM 0:00.00 httpd
nobody 309 0.0 1.4 2092 1704 ?? I 10:10AM 0:00.00 httpd
nobody 310 0.0 1.4 2092 1704 ?? I 10:10AM 0:00.00 httpd
nobody 311 0.0 1.4 2092 1704 ?? I 10:10AM 0:00.00 httpd
nobody 312 0.0 1.4 2092 1704 ?? I 10:10AM 0:00.00 httpd
genisis 317 0.0 0.8 1336 960 v1 Is+ 10:10AM 0:00.24 csh
root 320 0.0 0.5 920 628 v4 Is+ 10:10AM 0:00.02 getty
root 321 0.0 0.5 920 628 v5 Is+ 10:10AM 0:00.01 getty
root 322 0.0 0.5 920 628 v6 Is+ 10:10AM 0:00.01 getty
root 323 0.0 0.5 920 628 v7 Is+ 10:10AM 0:00.01 getty
nobody 324 0.0 0.3 832 348 ?? Is 10:10AM 0:00.01 unlinkd
root 992 0.0 0.5 920 628 v2 Is+ 3:46PM 0:00.01 getty
root 993 0.0 0.5 920 628 v3 Is+ 3:46PM 0:00.01 getty
genisis 994 0.0 0.8 1336 956 v0 Ss 3:46PM 0:00.14 csh
root 0 0.0 0.0 0 0 ?? DLs 5:10AM 0:00.02 swapper

Тепер я пошлю сигнал KILL спеціальним кодом -1 вiд імені суперкористувача:

$ su
Password:

# kill -9 -1

Ця команда справила на мене більше враження ніж попередня, оскільки я був викинутий з командного інтерпретатора в якому тільки що набрав команду kill. Після того, як я знову увійшов в систему, я визначив масштаб руйнувань наступним чином:

ps -acux
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
genisis 1070 0.0 0.2 396 244 v0 R+ 4:11PM 0:00.00 ps
root 1 0.0 0.2 532 304 ?? ILs 5:10AM 0:00.05 init
root 2 0.0 0.0 0 0 ?? DL 5:10AM 0:00.03 pagedaemon
root 3 0.0 0.0 0 0 ?? DL 5:10AM 0:00.00 vmdaemon
root 4 0.0 0.0 0 0 ?? DL 5:10AM 0:00.05 bufdaemon
root 5 0.0 0.0 0 0 ?? DL 5:10AM 0:02.65 syncer
root 1059 0.0 0.5 920 628 v3 Is+ 4:10PM 0:00.01 getty
root 1060 0.0 0.5 920 628 v2 Is+ 4:10PM 0:00.01 getty
root 1061 0.0 0.5 920 628 v7 Is+ 4:10PM 0:00.01 getty
root 1062 0.0 0.5 920 628 v6 Is+ 4:10PM 0:00.01 getty
root 1063 0.0 0.5 920 628 v5 Is+ 4:10PM 0:00.01 getty
genisis 1064 0.0 0.8 1336 956 v0 Ss 4:10PM 0:00.12 csh
root 1065 0.0 0.5 920 628 v4 Is+ 4:10PM 0:00.01 getty
root 1066 0.0 0.5 920 628 v1 Is+ 4:10PM 0:00.01 getty
root 0 0.0 0.0 0 0 ?? DLs 5:10AM 0:00.02 swapper

Коли суперкористувач посилає сигнал ідентифікатору -1, він розсилається всім процесам за винятком системних. Якщо цим сигналом буде KILL, то ви наслухається скарг від простих користувачів, у яких будуть втрачені всі відкриті ними, але не збережені файли даних.

Це є однією з причин, по якій тільки root може виконувати команди reboot і halt. Коли одна з цих команд запускається на виконання, то всім процесам розсилається сигнал TERM, для того що б дати їм шанс для збереження даних, оскільки за сигналом TERM, через деякий час, слід сигнал KILL, який надсилається для того що б гарантовано знищити всі процеси.

У наступній статті я продовжу цю тему, загостривши увагу на процесах init і getty.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*