Wysłanie kill -9 do procesu nie wymaga współpracy procesu (np. Obsługi sygnału), po prostu go zabija.
Zakładasz, że ponieważ niektóre sygnały można wychwycić i zignorować, wszystkie wymagają współpracy. Ale zgodnie z man 2 signal
„ sygnałami SIGKILL i SIGSTOP nie można złapać ani zignorować”. SIGTERM może zostać złapany, dlatego zwykły kill
nie zawsze jest skuteczny - ogólnie oznacza to, że coś w module obsługi procesu poszło nie tak. 1
Jeśli proces nie definiuje modułu obsługi dla danego sygnału (lub nie może go zdefiniować), jądro wykonuje akcję domyślną. W przypadku SIGTERM i SIGKILL ma to zakończyć proces (chyba, że jego pid wynosi 1; jądro się nie zakończy init
) 2, co oznacza, że jego uchwyty plików są zamknięte, jego pamięć jest zwrócona do puli systemowej, jego rodzic otrzymuje SIGCHILD, jego osierocone dzieci są dziedziczone przez init itp., tak jakby to wywołało exit
(patrz man 2 exit
). Proces już nie istnieje - chyba że skończy jako zombie, w którym to przypadku nadal jest wymieniony w tabeli procesów jądra z pewnymi informacjami; dzieje się tak, gdy jego rodzic niewait
i odpowiednio postępować z tymi informacjami. Jednak procesy zombie nie mają już przydzielonej pamięci i dlatego nie mogą kontynuować działania.
Czy istnieje coś takiego jak globalna tabela w pamięci, w której Linux przechowuje odniesienia do wszystkich zasobów zajętych przez proces, a kiedy „zabijam” proces, Linux po prostu przechodzi przez tę tabelę i uwalnia zasoby jeden po drugim?
Myślę, że to wystarczająco dokładne. Pamięć fizyczna jest śledzona według strony (jedna strona zwykle ma wielkość 4 KB), a strony te są pobierane i zwracane do globalnej puli. Jest to trochę bardziej skomplikowane, ponieważ niektóre bezpłatne strony są buforowane na wypadek, gdyby dane, które zawierają, były ponownie wymagane (to znaczy dane, które zostały odczytane z wciąż istniejącego pliku).
Strony mówią o „sygnałach”, ale na pewno to tylko abstrakcja.
Jasne, wszystkie sygnały są abstrakcją. Są konceptualne, podobnie jak „procesy”. Gram trochę w semantykę, ale jeśli masz na myśli, że SIGKILL różni się jakościowo od SIGTERM, to tak i nie. Tak w tym sensie, że nie można go złapać, ale nie w tym sensie, że oba są sygnałami. Analogicznie jabłko nie jest pomarańczą, ale jabłka i pomarańcze, zgodnie z przyjętą definicją, są owocami. SIGKILL wydaje się bardziej abstrakcyjny, ponieważ nie można go złapać, ale wciąż jest to sygnał. Oto przykład obsługi SIGTERM, jestem pewien, że widziałeś je już wcześniej:
#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;
}
Ten proces będzie po prostu spał na zawsze. Możesz uruchomić go w terminalu i wysłać SIGTERM za pomocą kill
. Wyrzuca rzeczy takie jak:
Recieved 15 from pid 25331, uid 1066.
1066 jest moim UID. Pid będzie odpowiadał powłoce, z której kill
jest wykonywany, lub pid zabicia, jeśli rozwidlisz go ( kill 25309 & echo $?
).
Ponownie nie ma sensu ustawiać modułu obsługi dla SIGKILL, ponieważ nie będzie on działać. 3 Jeśli ja kill -9 25309
proces się zakończy. Ale to wciąż sygnał; jądro ma informację o tym, kto wysłał sygnał , jaki to jest sygnał itp.
1. Jeśli nie przeglądałeś listy możliwych sygnałów , patrz kill -l
.
2. Kolejny wyjątek, jak wspomina Tim Post poniżej, dotyczy procesów w nieprzerwanym śnie . Nie można ich obudzić, dopóki problem nie zostanie rozwiązany, dlatego WSZYSTKIE sygnały (w tym SIGKILL) zostaną odłożone na czas trwania. Jednak proces nie może celowo stworzyć tej sytuacji.
3. Nie oznacza to, że używanie kill -9
jest lepszą rzeczą w praktyce. Mój przykładowy program obsługi jest zły w tym sensie, że do tego nie prowadzi exit()
. Prawdziwym celem procedury obsługi SIGTERM jest umożliwienie temu procesowi wyczyszczenia plików tymczasowych, a następnie dobrowolnego wyjścia. Jeśli użyjesz kill -9
, nie ma takiej szansy, więc rób to tylko wtedy, gdy część „dobrowolne wyjście” wydaje się nieudana.
kill -9
odniesienie .