L'invio di kill -9 a un processo non richiede la cooperazione del processo (come la gestione di un segnale), ma lo uccide.
Stai presumendo che, poiché alcuni segnali possono essere catturati e ignorati, tutti implicano una cooperazione. Ma secondo man 2 signal
"i segnali SIGKILL e SIGSTOP non possono essere catturati o ignorati". SIGTERM può essere catturato, motivo per cui la pianura kill
non è sempre efficace - in genere questo significa che qualcosa nel gestore del processo è andato storto. 1
Se un processo non definisce (o non può) un gestore per un determinato segnale, il kernel esegue un'azione predefinita. Nel caso di SIGTERM e SIGKILL, questo serve a terminare il processo (a meno che il suo PID non sia 1; il kernel non terminerà init
) 2 significa che i suoi handle di file sono chiusi, la sua memoria restituita al pool di sistema, il suo genitore riceve SIGCHILD, il suo orfano i bambini sono ereditati da init, ecc., proprio come se avesse chiamato exit
(vedi man 2 exit
). Il processo non esiste più - a meno che non finisca come uno zombi, nel qual caso è ancora elencato nella tabella dei processi del kernel con alcune informazioni; ciò accade quando il suo genitore nowait
e gestire correttamente queste informazioni. Tuttavia, ai processi di zombi non è più assegnata alcuna memoria e pertanto non possono continuare ad essere eseguiti.
C'è qualcosa come una tabella globale in memoria in cui Linux mantiene i riferimenti a tutte le risorse assorbite da un processo e quando "uccido" un processo Linux passa semplicemente attraverso quella tabella e libera le risorse una per una?
Penso che sia abbastanza preciso. La memoria fisica viene tracciata per pagina (una pagina di solito equivale a un blocco di 4 KB) e tali pagine vengono prese e restituite a un pool globale. È un po 'più complicato il fatto che alcune pagine liberate vengano memorizzate nella cache nel caso in cui i dati in esse contenuti siano nuovamente necessari (ovvero dati letti da un file ancora esistente).
Manpage parla di "segnali" ma sicuramente è solo un'astrazione.
Certo, tutti i segnali sono un'astrazione. Sono concettuali, proprio come i "processi". Sto giocando un po 'di semantica, ma se vuoi dire che SIGKILL è qualitativamente diverso da SIGTERM, allora sì e no. Sì nel senso che non può essere colto, ma no nel senso che sono entrambi segnali. Per analogia, una mela non è un'arancia, ma mele e arance sono, secondo una definizione preconcetta, entrambi frutti. SIGKILL sembra più astratto poiché non puoi prenderlo, ma è ancora un segnale. Ecco un esempio di gestione SIGTERM, sono sicuro che hai già visto questi prima:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
void sighandler (int signum, siginfo_t *info, void *context) {
fprintf (
stderr,
"Received %d from pid %u, uid %u.\n",
info->si_signo,
info->si_pid,
info->si_uid
);
}
int main (void) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = sighandler;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGTERM, &sa, NULL);
while (1) sleep(10);
return 0;
}
Questo processo dormirà per sempre. Puoi eseguirlo in un terminale e inviarlo con SIGTERM kill
. Sputa cose come:
Received 15 from pid 25331, uid 1066.
1066 è il mio UID. Il PID sarà quello della shell da cui kill
viene eseguito, o il PID di kill se lo fork ( kill 25309 & echo $?
).
Ancora una volta, non ha senso impostare un gestore per SIGKILL perché non funzionerà. 3 Se I kill -9 25309
il processo terminerà. Ma questo è ancora un segnale; il kernel ha le informazioni su chi ha inviato il segnale , che tipo di segnale è, ecc.
1. Se non hai guardato l'elenco dei possibili segnali , vedi kill -l
.
2. Un'altra eccezione, come cita Tim Post di seguito, si applica ai processi in modalità di sospensione ininterrotta . Questi non possono essere riattivati fino a quando il problema di fondo non viene risolto, quindi tutti i segnali (incluso SIGKILL) vengono rinviati per la durata. Un processo non può creare quella situazione di proposito, tuttavia.
3. Questo non significa che usare kill -9
sia una cosa migliore da fare in pratica. Il mio gestore di esempio è negativo nel senso che non porta a exit()
. Il vero scopo di un gestore SIGTERM è di dare al processo la possibilità di fare cose come ripulire i file temporanei, quindi uscire volontariamente. Se lo usi kill -9
, non ha questa possibilità, quindi fallo solo se la parte "esci volontariamente" sembra aver fallito.
kill -9
Riferimento obbligatorio .