Perché uno zombi sta aspettando il suo bambino?


11

Sto scavando attraverso diverse fonti, ma non riesco a trovare una buona descrizione dell'anatomia della raccolta dei bambini. Questo è un semplice caso di ciò che vorrei capire.

$ 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

Perché lo zombi sta aspettando il bambino?

Puoi spiegarlo? Devo conoscere C e leggere il codice sorgente di Bash per avere una comprensione più ampia di questo o c'è della documentazione? Ho già consultato:

GNU bash, versione 4.3.42 (1) -release (x86_64-pc-linux-gnu)

Linux 4.4.0-31-generic # 50-Ubuntu SMP mer 13 lug 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU / Linux


2
Dovresti notare che questo non ha nulla a che fare con bash (a parte il fatto che se scegli di usare bash come shell, molti processi verranno avviati da esso). Altre shell (tcsh, ksh, zsh e c) avviano tutti i processi ed eseguono essenzialmente le stesse funzioni del sistema operativo per gestirli.
jamesqf,

@jamesqf Interessante. Se desideri espandere il tuo commento in una risposta a tutti gli effetti, sarebbe fantastico.

1
Solo che non è proprio una risposta, sottolineando che hai cercato la risposta in posti sbagliati :-) Qualsiasi buon libro sulla programmazione di sistemi * nix dovrebbe fornire una risposta molto migliore di quella che potrei scrivere.
jamesqf,

Risposte:


17

Lo zombi non sta aspettando il suo bambino. Come ogni processo di zombi, rimane attivo fino a quando il suo genitore non lo raccoglie.

Dovresti visualizzare tutti i processi coinvolti per capire cosa sta succedendo e guardare anche il PPID. Usa questa riga di comando:

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

Il genitore del processo che stai uccidendo è cat. Quello che succede è che bash esegue il comando cat <( sleep 100 & wait )in background in una subshell. Poiché l'unica cosa che questa subshell fa è impostare un reindirizzamento e quindi eseguire un comando esterno, questa subshell viene sostituita dal comando esterno. Ecco il riassunto:

  • La bash originale (12126) chiama forkper eseguire il comando cat <( sleep 100 & wait )in background in un figlio (14247).
    • Il figlio (14247) chiama pipeper creare una pipe, quindi forkper creare un figlio per eseguire la sostituzione del processo sleep 100 & wait.
      • Il nipote (14248) chiama forkper correre sleep 100in background. Poiché il nipote non è interattivo, il processo in background non viene eseguito in un gruppo di processi separato. Quindi il nipote aspetta sleepdi uscire.
    • Il figlio (14247) chiama setpgid(è un lavoro in background in una shell interattiva in modo da ottenere il proprio gruppo di processi), quindi execveeseguire cat. (Sono un po 'sorpreso che la sostituzione del processo non avvenga nel gruppo di processi in background.)
  • Uccidi il nipote (14248). Il suo genitore è in esecuzione cat, che non sa nulla di alcun processo figlio e non ha chiamate commerciali wait. Poiché il genitore del nipote non lo raccoglie, il nipote rimane indietro come uno zombi.
  • Alla fine, catesce - o perché lo uccidi, o perché sleepritorna e chiude la pipe in modo da catvedere la fine del suo input. A quel punto, il genitore dello zombi muore, quindi lo zombi viene raccolto da init e init lo raccoglie.

Se si cambia il comando in

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

quindi catviene eseguito in un processo separato, non nel figlio del processo bash originale: il primo figlio deve rimanere indietro per eseguire echo done. In questo caso, se uccidi il nipote, non rimane come uno zombi, perché il bambino (che sta ancora correndo a quel punto) lo raccoglie.

Vedi anche In che modo Linux gestisce il processo di zombi e uno zombi può avere orfani? I bambini orfani saranno disturbati dalla mietitura dello zombi?


Sono stato sorpreso anche dalla cosa del gruppo di processo. Sembra che fosse un bug ed ora è stato corretto nel ramo master di bash.
PSkocik,

"La bash originale attende il suo bambino (14247)." Perché o in che modo? Il bambino dovrebbe essere eseguito in background e non c'è chiamata esplicita. Qual è la differenza tra l'originale bash (14246) in attesa di 14247 e 14247 (che è in esecuzione cat) che non aspetta 14248 (in attesa sleep)? C'è qualche ricordo di chi aspetta per chi, che il bambino (14247) ha perso e l'originale bash (14246) non lo ha fatto, o forse un elenco di segnali come SIGCHLD di chi dovrebbe essere chiamato e 14247 (ora in esecuzione bash) da cui non è stato effettuato l' iscrizione saluti al 14248?

1
@tomas Intendevo dire che l'originale bash chiama waitsuo figlio, cioè lo raccoglie. Vedo come questo potrebbe essere fonte di confusione, ho rimosso quella frase che non era nemmeno al punto giusto in termini cronologici. Le informazioni che un processo è morto vanno al genitore di quel processo, un processo non può "iscriversi" per ricevere informazioni sulla morte di qualche altro processo.
Gilles 'SO- smetti di essere malvagio' il

6

Lo zombi non sta aspettando il bambino. Invece, lo zombi è il processo che è già morto (di per sé o è stato ucciso - come nel tuo esempio), ha avuto il suo codice, i dati e lo stack allocati, e ora contiene solo il suo codice di uscita, in attesa che il suo genitore chiami wait(2)per recuperarlo (e quindi finalmente pulire completamente la voce di processo dalla tabella dei processi)

Nel tuo esempio, quando il sonno termina (o viene ucciso), il genitore leggerà gli stati di uscita e raccoglierà gli zombi. Vedi sopra menzionato wait(2)per i dettagli.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.