Sending kill -9 to a process doesn't require the process' cooperation (like handling a signal), it just kills it off.
Você está presumindo que, porque alguns sinais podem ser capturados e ignorados, todos envolvem cooperação. Mas, como por man 2 signal
, "os sinais SIGKILL e SIGSTOP não podem ser capturados ou ignorados". SIGTERM pode ser detectado, e é por isso que kill
não é sempre efetivo - geralmente isso significa que alguma coisa no manipulador do processo não deu certo. 1
Se um processo não define (ou não pode) definir um manipulador para um dado sinal, o kernel executa uma ação padrão. No caso de SIGTERM e SIGKILL, isso é terminar o process (a menos que seu pid seja 1; o kernel não terminará init
) 2 significando que seus filehandles são fechados, sua memória retornada ao sistema pool, seu pai recebe SIGCHILD, seus filhos órfãos são herdados por init, etc, como se tivesse chamado exit
(veja man 2 exit
). O processo não existe mais - a menos que acabe como um zumbi, caso em que ainda está listado na tabela de processos do kernel com alguma informação; isso acontece quando seu pai não wait
e lida com essa informação corretamente. No entanto, os processos zumbis não têm mais nenhuma memória alocada para eles e, portanto, não podem continuar sendo executados.
Is there something like a global table in memory where Linux keeps references to all resources taken up by a process and when I "kill" a process Linux simply goes through that table and frees the resources one by one?
Eu acho que isso é preciso o suficiente. A memória física é rastreada por página (uma página geralmente igual a um bloco de 4 KB) e essas páginas são obtidas e retornadas para um pool global. É um pouco mais complicado, pois algumas páginas gratuitas são armazenadas em cache, caso os dados contidos sejam novamente necessários (isto é, dados que foram lidos de um arquivo ainda existente).
Manpages talk about "signals" but surely that's just an abstraction.
Claro, todos os sinais são uma abstração. Eles são conceituais, assim como "processos". Eu estou jogando semântica um pouco, mas se você quer dizer que SIGKILL é qualitativamente diferente de SIGTERM, então sim e não. Sim, no sentido de que não pode ser capturado, mas não no sentido de que ambos são sinais. Por analogia, uma maçã não é uma laranja, mas maçãs e laranjas são, segundo uma definição preconcebida, ambas frutas. SIGKILL parece mais abstrato já que você não pode pegá-lo, mas ainda é um sinal. Aqui está um exemplo de tratamento SIGTERM, tenho certeza que você já viu isso antes:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
void sighandler (int signum, siginfo_t *info, void *context) {
fprintf (
stderr,
"Recieved %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;
}
Esse processo vai durar para sempre. Você pode executá-lo em um terminal e enviá-lo SIGTERM com kill
. Ele cospe coisas como:
Recieved 15 from pid 25331, uid 1066.
1066 é meu uid. O pid será o do shell do qual kill
é executado, ou o pid de kill se você for fork ( kill 25309 & echo $?
).
Novamente, não faz sentido configurar um manipulador para o SIGKILL porque ele não funcionará. 3 Se eu kill -9 25309
o processo for finalizado. Mas isso ainda é um sinal; o kernel tem a informação sobre quem enviou o sinal , que tipo de sinal ele é, etc.
1. Se você não viu a lista de possíveis sinais , consulte kill -l
.
2. Outra exceção, como Tim Post menciona abaixo, aplica-se a processos em suspensão ininterrupta . Estes não podem ser acordados até que o problema subjacente seja resolvido e, portanto, TODOS os sinais (incluindo o SIGKILL) sejam adiados por toda a duração. Um processo não pode criar essa situação de propósito, no entanto.
3. Isso não significa usar kill -9
é uma coisa melhor para fazer na prática. Meu manipulador de exemplo é ruim, no sentido de que não leva a exit()
. O propósito real de um manipulador SIGTERM é dar ao processo uma chance de fazer coisas como limpar arquivos temporários e, depois, sair voluntariamente. Se você usar kill -9
, ele não terá essa chance, portanto, faça isso apenas se a parte "sair voluntariamente" tiver falhado.