Kiedy killall -9 name
zabijałem program, stan stał się zombie. Kilka minut później naprawdę przestało. Co się dzieje w tych minutach?
Program faktycznie nigdy nie odbiera sygnału SIGKILL, ponieważ SIGKILL jest całkowicie obsługiwany przez system operacyjny / jądro.
Kiedy SIGKILL dla określonego procesu jest wysyłany, program planujący jądra natychmiast przestaje dawać temu procesowi więcej czasu procesora na uruchomienie kodu przestrzeni użytkownika. Jeśli proces ma wątki wykonujące kod przestrzeni użytkownika na innych procesorach / rdzeniach w momencie, gdy program planujący podejmie tę decyzję, wątki te również zostaną zatrzymane. (W systemach jednordzeniowych było to o wiele prostsze: jeśli jedynym rdzeniem procesora w systemie był program planujący, z definicji nie działałby on jednocześnie!)
Jeśli proces / wątek wykonuje kod jądra (np. Wywołanie systemowe lub operację I / O skojarzoną z plikiem odwzorowanym w pamięci) w czasie SIGKILL, robi się to nieco trudniejsze: tylko niektóre wywołania systemowe są przerywane, więc jądro wewnętrznie zaznacza proces jako będący w specjalnym stanie „umierania” do czasu rozwiązania wywołań systemowych lub operacji we / wy. Czas procesora na ich rozwiązanie zostanie zaplanowany jak zwykle. Przerywalne wywołania systemowe lub operacje we / wy sprawdzą, czy proces, który je wywołał, umiera w odpowiednich punktach zatrzymania, i w takim przypadku zakończą się wcześniej. Operacje nieprzerwane dobiegną końca i sprawdzą stan „umierania” tuż przed powrotem do kodu przestrzeni użytkownika.
Po rozwiązaniu procedur wewnętrznych jądra stan procesu zmienia się z „umierania” na „martwy”, a jądro zaczyna go oczyszczać, podobnie jak w przypadku normalnego zakończenia programu. Po zakończeniu czyszczenia zostanie przypisany kod wynikowy większy niż 128 (aby wskazać, że proces został zabity sygnałem; zobacz tę odpowiedź, aby uzyskać bałagan w szczegółach ), a proces przejdzie w stan „zombie” . Rodzic zabitego procesu zostanie powiadomiony sygnałem SIGCHLD.
W rezultacie sam proces nigdy nie będzie miał szansy na przetworzenie informacji o otrzymaniu SIGKILL.
Gdy proces znajduje się w stanie „zombie”, oznacza to, że proces jest już martwy, ale jego proces nadrzędny jeszcze tego nie potwierdził, odczytując kod zakończenia martwego procesu za pomocą wait(2)
wywołania systemowego. Zasadniczo jedynym zasobem, który zużywa proces zombie, jest miejsce w tabeli procesów, w którym znajduje się jego PID, kod wyjścia i niektóre inne „istotne statystyki” procesu w chwili jego śmierci.
Jeśli proces nadrzędny umiera przed swoimi potomkami, osierocone procesy potomne są automatycznie adoptowane przez PID # 1, który ma szczególny obowiązek ciągłego wywoływania wait(2)
, aby żadne osierocone procesy nie pozostały jak zombie.
Jeśli wyczyszczenie procesu zombie zajmuje kilka minut, sugeruje to, że proces nadrzędny zombie ma trudności lub nie wykonuje prawidłowo swojej pracy.
Mówiący z przymrużeniem oka, co robić w przypadku problemów z zombie w systemach operacyjnych typu Unix: „Nie możesz nic zrobić dla samych zombie, ponieważ są one już martwe. Zamiast tego zabij złego mistrza zombie! ” (tj. proces macierzysty kłopotliwych zombie)
ps
: „S” oznacza, że I / O czeka na anulowanie jądra w celu dostarczenia sygnału, a „D” dla tych, których nie może.