Cosa fa un programma quando viene inviato il segnale SIGKILL?


39

Quando killall -9 nameuccidevo un programma, lo stato diventava zombi. Alcuni minuti dopo, si è fermato davvero. Quindi, cosa sta succedendo in quei minuti?

Risposte:


66

Il programma in realtà non riceve mai il segnale SIGKILL, poiché SIGKILL è completamente gestito dal sistema operativo / kernel.

Quando viene inviato SIGKILL per un processo specifico, lo scheduler del kernel smette immediatamente di concedere a quel processo altro tempo CPU per l'esecuzione del codice spazio utente. Se il processo ha dei thread che eseguono il codice dello spazio utente su altre CPU / core nel momento in cui lo scheduler prende questa decisione, anche questi thread verranno arrestati. (Nei sistemi single-core questo era molto più semplice: se l'unico core della CPU nel sistema eseguiva lo scheduler, per definizione non eseguiva il processo allo stesso tempo!)

Se il processo / thread sta eseguendo il codice del kernel (ad esempio una chiamata di sistema o un'operazione I / O associata a un file mappato in memoria) al momento di SIGKILL, diventa un po 'più complicato: solo alcune chiamate di sistema sono interrompibili, quindi il il kernel contrassegna internamente il processo in uno stato speciale "morente" fino a quando il sistema chiama o le operazioni di I / O vengono risolte. Il tempo della CPU per risolverli verrà programmato come al solito. Le chiamate di sistema interrompibili o le operazioni di I / O verificheranno che il processo che le ha chiamate stia morendo in tutti i punti di arresto adeguati e in quel caso uscirà presto. Le operazioni ininterrotte verranno completate e verificheranno lo stato "morente" appena prima di ritornare al codice dello spazio utente.

Una volta risolte le routine del kernel in-process, lo stato del processo passa da "morendo" a "morto" e il kernel inizia a ripulirlo, come quando un programma esce normalmente. Una volta completata la pulizia, verrà assegnato un codice risultato superiore a 128 (per indicare che il processo è stato interrotto da un segnale; vedere questa risposta per i dettagli disordinati ) e il processo passerà allo stato "zombi" . Il genitore del processo ucciso verrà avvisato con un segnale SIGCHLD.

Di conseguenza, il processo stesso non avrà mai la possibilità di elaborare effettivamente le informazioni che ha ricevuto un SIGKILL.

Quando un processo è in uno stato "zombi" significa che il processo è già morto, ma il suo processo genitore non lo ha ancora riconosciuto leggendo il codice di uscita del processo morto usando la wait(2)chiamata di sistema. Fondamentalmente l'unica risorsa che un processo zombi sta consumando di più è uno slot nella tabella dei processi che contiene il suo PID, il codice di uscita e alcune altre "statistiche vitali" del processo al momento della sua morte.

Se il processo genitore muore prima dei suoi figli, i processi figlio orfani vengono automaticamente adottati dal PID n. 1, che ha il dovere speciale di continuare a chiamare in wait(2)modo che eventuali processi orfani non rimangano come zombi.

Se ci vogliono diversi minuti per completare un processo di zombi, ciò suggerisce che il processo genitore dello zombi sta lottando o non sta facendo il suo lavoro correttamente.

C'è una descrizione ironica su cosa fare in caso di problemi con gli zombi nei sistemi operativi simili a Unix: "Non puoi fare nulla per gli stessi zombi, poiché sono già morti. Invece, uccidi il malvagio maestro di zombi! " (cioè il processo genitore degli zombi fastidiosi)


5
Cosa succede se il processo è in una chiamata del kernel (es. Facendo I / O) quando viene inviato SIGKILL?
salta il

9
@gidds L'I / O verrà annullato per eseguire il SIGKILL o il SIGKILL verrà ritardato fino al completamento dell'I / O. Questa è la differenza tra gli stati di sospensione 'S' e 'D' in ps: 'S' sta per I / O in attesa che il kernel possa annullare per inviare un segnale, e 'D' per quelli che non può.
zwol,

6
Non è del tutto esatto affermare che la pianificazione si interrompe immediatamente dando tempo alla CPU del processo. Il lato kernel della gestione del segnale è ancora eseguito da quel processo, ma il processo eseguirà solo il codice del kernel, quindi hai ragione quando dici che il programma non riceve mai il segnale. Il processo eseguirà il codice del kernel responsabile della maggior parte delle operazioni di cleanup delle risorse (file aperti, memoria virtuale, ecc.). Gli ultimi passaggi di questo codice di cleanup sono cambiare lo stato del processo in zombie e invocare lo scheduler. Quindi non sarà mai più programmato.
Kasperd,

4
@gidds Ci sono almeno quattro stati diversi in cui può trovarsi il processo. Al momento può eseguire il codice del kernel o può dormire in uno dei tre diversi stati di sospensione. Gli stati di sonno possono essere interrompibili, non interrompibili o non interrompibili, ad eccezione dei segnali mortali. Se è in un sonno non interrompibile, sarà lasciato dormire per tutto il tempo necessario e solo una volta che si sveglierà avrà la possibilità di morire. Se si trovava in uno degli altri due stati di sospensione, verrà svegliato immediatamente e pianificato non appena sarà disponibile una CPU.
Kasperd,

2
@gidds Quello che succede dopo dipende dal codice del kernel in esecuzione. Indipendentemente dal fatto che fosse già in esecuzione o che prima fosse necessario svegliarlo e che quindi potesse iniziare a eseguire il codice del kernel in cui si trovava al momento, sarà permesso di continuare. E quel codice del kernel è responsabile di notare che al processo è stato detto di morire e agire di conseguenza. Il più delle volte il modo corretto di gestirlo nel codice del kernel è quello di restituire un errore da qualunque funzione stia eseguendo. Una volta che lo stack di chiamate del kernel è stato svolto, il codice di gestione del segnale può prendere il controllo appena prima di tornare alla modalità utente.
Kasperd,
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.