W systemie UNIX, gdy proces nadrzędny znika, myślałem, że wszystkie procesy podrzędne resetują init jako nadrzędne. Czy to nie jest poprawne przez cały czas? Czy są jakieś wyjątki?
W systemie UNIX, gdy proces nadrzędny znika, myślałem, że wszystkie procesy podrzędne resetują init jako nadrzędne. Czy to nie jest poprawne przez cały czas? Czy są jakieś wyjątki?
Odpowiedzi:
Przeniesienie mojego komentarza do odpowiedzi .... Nie wierzę, że są wyjątki.
Stwierdzono, że „czasami proces nadrzędny jest zabijany przed zabiciem jego elementu podrzędnego. W tym przypadku proces„ nadrzędny wszystkich procesów ” init
staje się nowym PPID (identyfikator procesu nadrzędnego). Czasami procesy te nazywane są procesami osieroconymi.” źródło
Podobnie jest opisane w blogu IBM : „Rodzic umiera lub zostaje zabity przed dzieckiem. W powyższym scenariuszu proces potomny staje się procesem osieroconym (ponieważ stracił swojego rodzica). W Linuksie init
proces przychodzi na ratunek sierota przetwarza je i adoptuje. Oznacza to, że po tym, jak dziecko straciło swojego rodzica, init
proces staje się nowym procesem nadrzędnym ”.
Trzy odpowiedzi napisane w 2014 roku, wszystkie mówią, że w Unices i Linuksie proces ten jest przetwarzany ponownie w celu przetworzenia nr 1 bez wyjątku. Trzy złe odpowiedzi. ☺
Jak mówi SUS , cytowany w jednej z pozostałych odpowiedzi tutaj, więc nie będę go więcej cytował, proces nadrzędny osieroconych dzieci jest ustawiony na proces zdefiniowany w ramach implementacji . Cristian Ciupitu ma prawo przejrzeć dokumentację Linuksa, aby zobaczyć, co definiuje implementacja. Ale wprowadza go w błąd przez tę dokumentację, która jest niespójna i nieaktualna.
Dwa lata przed napisaniem tych trzech odpowiedzi i szybko, nawet trzy lata temu, w momencie pisania tej odpowiedzi, jądro Linuksa uległo zmianie. Systematyczni programiści dodali możliwość skonfigurowania procesów jako „podrzędnych”. Począwszy od Linuksa 3.4 procesy mogą prctl()
wywoływać wywołanie systemowe z PR_SET_CHILD_SUBREAPER
opcją, w wyniku czego nie przetwarzają # 1, stają się rodzicami dowolnych swoich osieroconych procesów potomnych. Strona podręcznika dlaprctl()
jest aktualna, ale inne strony podręcznika nie zostały zaktualizowane i są spójne.
W wersji 10.2 FreeBSD zyskał tę samą zdolność, rozszerzając swoje istniejące procctl()
wywołanie systemowe z opcjami PROC_REAP_ACQUIRE
i PROC_REAP_RELEASE
. Przyjęła ten mechanizm od DragonFly BSD; który zyskał go w wersji 4.2, pierwotnie nazwany, reapctl()
ale podczas projektowania zmieniany na procctl()
.
Istnieją więc wyjątki i dość znaczące: w Linuksie, FreeBSD / PC-BSD i DragonFly BSD proces nadrzędny osieroconych dzieci jest ustawiany na proces najbliższego przodka dziecka oznaczony jako podsiadacz lub proces nr 1 jeśli nie ma procesu podrzędnego dla żniwiarza przodka. Różne narzędzia nadzoru demona - w tym systemd (ten, którego programiści umieścili to w jądrze Linuksa w pierwszej kolejności), upstart i nosh service-manager
- już z tego korzystają.
Jeżeli taka osoba nadzorująca demon nie jest przetwarzać nr 1 i ikra usługi, takie jak interaktywny sesji logowania, oraz tym, że jedna sesja robi się (dość uparty) sztuczki z próbą „daemonize” przez podwójnie fork()
ING , to czyjaś proces będzie skończy jako dziecko nadzorcy demonów, a nie procesu nr 1. Oczywistym błędem jest oczywiście oczekiwanie, że będzie można bezpośrednio odradzać demony z sesji logowania. Ale to kolejna odpowiedź.
procctl()
. Strony podręcznika DragonFly BSD. § 2Według strony podręcznika exit
ze specyfikacji Single UNIX®, wersja 2:
Identyfikator procesu nadrzędnego wszystkich istniejących procesów potomnych i procesów zombie procesu wywołującego jest ustawiony na identyfikator procesu systemu zależnego od implementacji. Oznacza to, że procesy te są dziedziczone przez specjalny proces systemowy.
Dla większości wariantów uniksowych tym specjalnym procesem jest init
(PID 1).
wait(2)
Strona podręcznika systemu Linux to potwierdza:
Jeśli proces nadrzędny zostanie zakończony, jego dzieci „zombie” (jeśli istnieją) są adoptowane przez init (8), który automatycznie wykonuje oczekiwanie na usunięcie zombie.
Potwierdzają to również strony wait(2)
podręcznika FreeBSD , NetBSD wait(2)
, OpenBSD wait(2)
i Mac OS X wait(2)
:
Jeśli proces nadrzędny zakończy się bez oczekiwania na zakończenie wszystkich procesów podrzędnych, pozostałym procesom podrzędnym zostanie przypisany identyfikator procesu nadrzędnego 1 (identyfikator procesu inicjującego).
Strona podręcznika Oracle Solaris 11.1 wait(3C)
również to potwierdza:
Jeśli proces nadrzędny zakończy się bez oczekiwania na zakończenie swoich procesów podrzędnych, identyfikator procesu nadrzędnego każdego procesu podrzędnego jest ustawiony na 1, przy czym proces inicjowania dziedziczy procesy podrzędne; zob
Intro(2)
.
Nie wierzę w to. Zawsze przechodzi do procesu inicjowania.