Чому зомбі чекає свою дитину?


11

Я копаю різні джерела, але не можу знайти хорошого опису анатомії пожинання дитини. Це простий випадок того, що я хотів би зрозуміти.

$ cat <( sleep 100 & wait ) &
[1] 14247
$ ps ax -O pgid | grep $$
12126 12126 S pts/17   00:00:00 bash
14248 12126 S pts/17   00:00:00 bash
14249 12126 S pts/17   00:00:00 sleep 100
14251 14250 S pts/17   00:00:00 grep --color=auto 12126
$ kill -2 14248

$ ps ax -O pgid | grep $$
12126 12126 S pts/17   00:00:00 bash
14248 12126 Z pts/17   00:00:00 [bash] <defunct>
14249 12126 S pts/17   00:00:00 sleep 100
14255 14254 S pts/17   00:00:00 grep --color=auto 12126

Чому зомбі чекає дитину?

Чи можете ви пояснити це? Чи потрібно мені знати C та читати вихідний код Bash, щоб отримати більш широке розуміння цього чи є документація? Я вже радився:

GNU bash, версія 4.3.42 (1) -випуск (x86_64-pc-linux-gnu)

Linux 4.4.0-31-generic # 50-Ubuntu SMP ср 13 липня 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU / Linux


2
Слід зазначити, що це насправді не має нічого спільного з bash (крім того, що якщо ви вирішите використовувати bash як свою оболонку, багато процесів буде запущено ним). Інші оболонки (tcsh, ksh, zsh, & c) запускають всі процеси і виконують по суті ті ж функції ОС для боротьби з ними.
jamesqf

@jamesqf Цікаво. Якщо ви хочете розгорнути свій коментар до повноцінної відповіді, це було б чудово.

1
За винятком того, що це насправді не відповідь, просто зазначивши, що ви шукали відповідь у неправильних місцях :-) Будь-яка хороша книга про програмування * nix систем повинна дати набагато кращу відповідь, ніж я могла написати.
jamesqf

Відповіді:


17

Зомбі не чекає своєї дитини. Як і будь-який процес зомбі, він залишається навколо, поки його батько не збирає його.

Ви повинні відобразити всі пов'язані процеси, щоб зрозуміти, що відбувається, а також переглянути PPID. Використовуйте цей командний рядок:

ps -t $(tty) -O ppid,pgid

Батьком процесу, який ви вбиваєте, є cat. Що відбувається, це те, що bash запускає фонову команду cat <( sleep 100 & wait )в нижній частині. Оскільки єдине, що робить ця підпакет - це налаштувати деяке перенаправлення та виконати зовнішню команду, ця підзарядка замінюється зовнішньою командою. Ось такий пробіг:

  • Оригінальний bash (12126) закликає forkвиконати фонову команду cat <( sleep 100 & wait )у дитини (14247).
    • Дитина (14247) закликає pipeстворити трубу, потім forkстворити дитину для запуску процесу заміни sleep 100 & wait.
      • Онук (14248) закликає forkбігати sleep 100на задньому плані. Оскільки онук не є інтерактивним, фоновий процес не працює в окремій групі процесів. Потім онук чекає sleepвиходу.
    • Дитина (14247) дзвонить setpgid(це фонове завдання в інтерактивній оболонці, щоб отримати власну групу процесів), а потім execveзапустити cat. (Я трохи здивований, що підміна процесу не відбувається у фоновій групі процесів.)
  • Ти вбиваєш онука (14248). Його батько працює cat, який нічого не знає про будь-який процес дитини і не має ділових дзвінків wait. Оскільки батько онука не пожинає, онук залишається позаду як зомбі.
  • Врешті-решт, catвиходить - або тому, що ви вбиваєте її, або тому, що sleepповертає та закриває трубу, тому catбачить кінець її вводу. У цей момент батько зомбі помирає, тож зомбі збирається за допомогою init і init пожинає його.

Якщо ви змінили команду на

{ cat <( sleep 100 & wait ); echo done; } &

потім catзапускається в окремому процесі, а не в дитині початкового процесу bash: перша дитина повинна залишатися позаду, щоб бігти echo done. У цьому випадку, якщо ви вбите онука, це не залишатиметься зомбі, тому що дитина (яка в цей момент все ще біжить).

Див. Також Як linux обробляє процес зомбі та чи може зомбі мати дітей-сиріт? Чи будуть турбуватися діти-сироти, пожинаючи зомбі?


Я також був здивований процесом групової роботи. Схоже, це була помилка, і тепер вона виправлена ​​у гілці головного башма.
PSkocik

"Оригінальний баш чекає своєї дитини (14247)." Чому чи яким чином? Дитина повинна бігати на задньому плані, і явного дзвінка немає. Яка різниця між оригінальним bash (14246), який чекає 14247, і 14247 (який працює cat), не чекаючи 14248 (чекає sleep)? Чи є якась пам’ять того, хто кого чекає, чого дитина (14247) втратив і оригінальний баш (14246) не зробив, або, можливо, список сигналів типу SIGCHLD того, кого слід викликати, і 14247 (зараз працює bash) скасовано з підпискою на стосується 14248?

1
@tomas Я мав на увазі, що оригінальний баш закликає waitсвою дитину, тобто він її пожинає. Я бачу, як це буде заплутано, я вилучив це речення, яке навіть не було в хронологічному відношенні. Інформація про те, що процес загинула, надходить до батьківського процесу, процес не може "підписатися", щоб отримати інформацію про смерть якогось іншого процесу.
Жил "ТАК - перестань бути злим"

6

Зомбі не чекає дитини. Натомість зомбі - це процес, який уже загинув (самостійно, або був убитий - як у вашому прикладі), розмістив свій код, дані та стек, і тепер містить лише свій вихідний код, очікуючи, що його батько зателефонує, wait(2)щоб отримати його (і, таким чином, остаточно очистити запис процесу з таблиці процесів)

У вашому прикладі, коли сон закінчується (або вбивається), батько читатиме статуси виходу та пожинає зомбі. Детальніше див. Вище wait(2).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.