Enviar kill -9 para um processo não requer a cooperação do processo (como manipular um sinal), apenas o mata.
Você está presumindo que, porque alguns sinais podem ser capturados e ignorados, todos envolvem cooperação. Mas, de acordo com man 2 signal
"os sinais SIGKILL e SIGSTOP não podem ser capturados ou ignorados". O SIGTERM pode ser capturado, e é por isso que a planície kill
nem sempre é eficaz - geralmente isso significa que algo no manipulador do processo deu errado. 1 1
Se um processo não define (ou não pode) definir um manipulador para um determinado sinal, o kernel executa uma ação padrão. No caso de SIGTERM e SIGKILL, é para finalizar o processo (a menos que seu PID seja 1; o kernel não será finalizado init
) 2 significa que seus identificadores de arquivo estão fechados, sua memória retornada ao pool do sistema, seu pai recebe SIGCHILD, seu órfão os filhos são herdados pelo init, etc., como se tivesse chamado exit
(veja man 2 exit
). O processo não existe mais - a menos que acabe como um zumbi; nesse caso, ele ainda está listado na tabela de processos do kernel com algumas informações; isso acontece quando seu pai nãowait
e lide com essas informações corretamente. No entanto, os processos zumbis não têm mais memória alocada para eles e, portanto, não podem continuar sendo executados.
Existe algo como uma tabela global na memória em que o Linux mantém referências a todos os recursos ocupados por um processo e quando eu "mato" um processo, o Linux simplesmente passa por essa tabela e libera os recursos um por um?
Eu acho que é preciso o suficiente. A memória física é rastreada por página (uma página geralmente igual a um pedaço de 4 KB) e essas páginas são obtidas e retornadas a um pool global. É um pouco mais complicado, pois algumas páginas liberadas são armazenadas em cache, caso os dados contidos sejam necessários novamente (ou seja, dados que foram lidos em um arquivo ainda existente).
As páginas de manual falam sobre "sinais", mas certamente isso é apenas uma abstração.
Claro, todos os sinais são uma abstração. Eles são conceituais, assim como "processos". Estou jogando semântica um pouco, mas se você quer dizer que o SIGKILL é qualitativamente diferente do SIGTERM, 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 é laranja, mas maçãs e laranjas são, de acordo com uma definição preconcebida, ambas frutas. SIGKILL parece mais abstrato, pois você não pode pegá-lo, mas ainda é um sinal. Aqui está um exemplo de manipulação do 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,
"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;
}
Este processo irá dormir para sempre. Você pode executá-lo em um terminal e enviá-lo com o SIGTERM kill
. Ele cospe coisas como:
Received 15 from pid 25331, uid 1066.
1066 é o meu UID. O PID será aquele do shell a partir do qual kill
é executado ou o PID de kill se você o bifurcar ( kill 25309 & echo $?
).
Novamente, não faz sentido definir um manipulador para o SIGKILL porque ele não funcionará. 3 Se eu, kill -9 25309
o processo será encerrado. Mas isso ainda é um sinal; o kernel possui informações sobre quem enviou o sinal , que tipo de sinal é etc.
1. Se você não examinou 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 . Eles não podem ser acordados até que o problema subjacente seja resolvido e, portanto, TODOS os sinais (incluindo o SIGKILL) foram adiados pela duração. Um processo não pode criar essa situação de propósito, no entanto.
3. Isso não significa que usar kill -9
é a melhor coisa a se fazer na prática. Meu manipulador de exemplo é ruim no sentido em que não leva exit()
. O verdadeiro objetivo de um manipulador SIGTERM é dar ao processo a chance de fazer coisas como limpar arquivos temporários e sair voluntariamente. Se você usar kill -9
, ela não terá essa chance, então faça isso apenas se a parte "sair voluntariamente" parecer ter falhado.
kill -9
Referência obrigatória .