Jak wewnętrzne zamknięcie systemu jądra Linuksa działa?

28

Mam niejasny pomysł na to, jak przestrzeń użytkownika i init-system (czy to klasyczny init sysV / upstart / systemd) działają podczas zamykania systemu. (Zasadniczo istnieje kolejność zamówień „Stop!”, „Proszę przestań teraz naprawdę”, „Proces muszę cię zabić, aby zatrzymać” i czekanie… rzeczy się dzieją).

W każdym razie jestem bardzo nieświadomy, jak działa zamknięcie systemu w jądrze (gdzie na pewno jest też wiele rzeczy do zrobienia)?

Próbowałem zajrzeć do dokumentacji jądra https://www.kernel.org/doc/htmldocs/, a nawet skorzystałem z narzędzia wyszukiwania PAL NSA, aby dać mi przewagę w odkrywaniu, jak to działa.

Przeszukałem również SE U + L i nic nie znalazłem (przeoczyłem?)

W każdym razie pytanie, choć potencjalnie nieco trudne, zasługuje na odpowiedź w tej sieci pytań i odpowiedzi, ponieważ zakładam, że więcej osób jest zainteresowanych otrzymaniem szkicu tego, co dzieje się w jądrze Linuksa podczas zamykania.

Potencjalnie nastąpiła również zmiana łącza do bardziej szczegółowych wyjaśnień.

Odpowiedź może zawierać pytanie, które wywołania systemowe i jakie sygnały jądra są używane?

https://github.com/torvalds/linux/blob/b3a3a9c441e2c8f6b6760de9331023a7906a4ac6/arch/x86/kernel/reboot.c wydaje się być plikiem używanym w x86 związanym z ponownym uruchomieniem komputera (już blisko zamykania, co?)

może fragment kodu znaleziony tutaj http://lxr.free-electrons.com/source/kernel/reboot.c#L176 może zostać użyty do wyjaśnienia

176 void kernel_power_off (void)
177 {
178 kernel_shutdown_prepare (SYSTEM_POWER_OFF);
179 if (pm_power_off_prepare)
180 pm_power_off_prepare ();
181 migrate_to_reboot_cpu ();
182 syscore_shutdown ();
183 pr_emerg („Wyłączanie \ n”);
184 kmsg_dump (KMSG_DUMP_POWEROFF);
185 machine_power_off ();
186}
187 EXPORT_SYMBOL_GPL (kernel_power_off);
ludzkośćANDpeace
źródło
8
niech jednorożec będzie z tobą
Kiwy
1
@Kiwy dzięki za sugestię. Zaakceptuję po pewnym czasie, zanim pojawią się potencjalnie lepsze odpowiedzi. Ale przynajmniej odpowiedź jest już dostępna.
humanityANDpeace
Nie dziękuj mi, dzięki Unicorn!
Kiwy,
Należy pamiętać, że istnieje opcja wyskakiwania przez okno do shutdown(8)np. Przestarzałej, -n którą, jak sądzę, w starej dokumentacji uniksowej użyto do przeczytania „ sami zamknij system - rdzeń jest NA OGNIU! ”, Skutecznie zabłąkany przełącznik zabijania systemu, który pozostawiłby / mógłby zostawić kawałki rozrzucone na podłodze (a przynajmniej systemy plików w stanie uszkodzonym) - można sobie wyobrazić, że byłby on używany w systemie typu ramy głównej, w którym ktoś właśnie złapał rękę w wentylator. 🕱
SlySven

Odpowiedzi:

26

Główne zasoby pozwalające zrozumieć, jak działa jądro Linuksa:

  1. Dokumentacja .
  2. Linux Weekly News artykuły .
  3. Źródło. Jest to złożona bestia, która jest nieco łatwiejsza do zrozumienia dzięki LXR , linuksowemu odnośnikowi. Wariant LXR działający na lxr.linux.no jest ładniejszy od innych, ale często jest nieczynny.

W tym przypadku nie mogę znaleźć niczego istotnego centralnie w dokumentacji lub na LWN, więc LXR jest.

Ostatnią rzeczą, którą robi kod użytkownika, jest wywołanie wywołania rebootsystemowego . Wymaga 4 argumentów, więc wyszukaj SYSCALL_DEFINE4(rebootna LXR, co prowadzi do kernel/reboot.c. Po sprawdzeniu uprawnień osoby dzwoniącej oraz argumenty, punkt wejścia syscall nazywa jedną z kilku funkcji: kernel_restartdo restartu, kernel_haltaby zatrzymał się na napięty pętli, kernel_poweroffdo wyłączenia zasilania systemu, kernel_kexecaby zastąpić jądro na nową (jeśli jest skompilowany w), lub hibernateaby zapisać pamięć na dysku przed wyłączeniem.

kernel_restart, kernel_haltI kernel_power_offsą dość podobne:

  1. Przejrzyj reboot_notifier_list, która jest listą haków, które komponenty jądra mogą zarejestrować, aby wykonać kod po wyłączeniu zasilania. Na tym etapie tylko kilku kierowców musi wykonać kod, głównie stróżów.
  2. Ustaw system_statezmienną.
  3. Wyłącz pomocnika trybu użytkownika , aby mieć pewność, że kod użytkownika nie będzie już uruchamiany. (Na tym etapie mogą nadal istnieć procesy).
  4. Zadzwoń, device_shutdownaby zwolnić lub wyłączyć wszystkie urządzenia w systemie. Wielu kierowców dołącza do tego etapu.
    Należy zauważyć, że wszelkie systemy plików, które są nadal montowane w tym momencie, są skutecznie wymontowane. Osoba wywołująca wywołanie systemowe bierze odpowiedzialność za każde czyste odmontowanie.
  5. Wyłącznie w przypadku wyłączenia zasilania, jeśli ACPI jest skonfigurowane, prawdopodobnie wykonaj kod, aby przygotować przejście do stanu ACPI S5 (miękkie wyłączenie zasilania).
  6. W maszynie wieloprocesorowej kod może działać na dowolnym procesorze, w zależności od tego, które wywołało wywołanie systemowe. migrate_to_reboot_cpudba o przełączenie na jeden konkretny procesor i zapobiega wysyłaniu kodu przez harmonogram do innych procesorów. Po tym punkcie działa tylko jeden procesor.
  7. syscore_shutdownwywołuje shutdownmetodę zarejestrowanych operacji syscore . Myślę, że chodzi głównie o wyłączenie przerwań; kilka haczyków ma shutdownmetodę.
  8. Zaloguj wiadomość informacyjną - piosenka łabędzia.
  9. Wreszcie udać się na spoczynek w jakiś sposób zależne od maszyny dzwoniąc machine_restart, machine_haltlub machine_power_off.

Hibernacji kod przechodzi przez następujące etapy:

  1. Iteruj przez haki zarządzania energią .
  2. Synchronizuj systemy plików.
  3. Zatrzymaj cały kod użytkownika .
  4. Zapobiegaj podłączaniu urządzenia podczas pracy .
  5. Zrzuć stan systemu do przestrzeni wymiany.
  6. Jeśli wszystko się powiedzie, hibernuj sprzęt . Może to obejmować dzwoni kernel_restart, kernel_haltalbo kernel_power_off, albo jakiś specyficzny sposób platforma hibernacji.

Innym sposobem zamknięcia systemu jest machine_emergency_restart. Jest to wywoływane przez magiczny klucz SysRqB . OKlucz działa inaczej: to nazywakernel_power_off .

System może również zostać wyłączony z powodu paniki , czyli błędu nie do naprawienia. Panikowanie próbuje zarejestrować komunikat, a następnie zrestartować system (poprzez sprzętowy organ nadzorczy lub awaryjny restart).

Gilles „SO- przestań być zły”
źródło
+1 dzięki! @Gilles, jeśli chcesz zaimplementować jakiś kod, który wyczyści / odkaże pamięć RAM maszyny, jako ostatni krok, zarejestrujesz operację syscore dla syscore_shutdown(tj. To rozwiązałoby moje inne pytanie unix.stackexchange.com/q/122540/24394 ) . Zarówno krok (1), jak i krok (7) pozwalają zarejestrować rzeczy do wykonania przy wyłączaniu, a nie wiedzieć, co + miałem wrażenie, że na kolejność wykonywania tych wywołań zwrotnych w (1) i (7) nie można wpłynąć! Będę doktorami, o których wspomniałeś, ale jeśli wiesz! dzięki!
humanityANDpeace
Dziwi mnie to pytanie, a odpowiedź nie ma więcej pozytywnych opinii.
2

To tylko częściowa odpowiedź i na pewno zapraszam na inną odpowiedź, która może być bardziej wyczerpująca i jasna.

Treść tej odpowiedzi pochodzi z kernel/reboot.cpliku jądra linuksa 3.13 (co może nie być pierwszym przypuszczeniem, ponieważ nazwa nie jest zamknięta. C, ale uruchomiona ponownie. C)

W każdym razie mamy w zasadzie trzy funkcje, które szkicują proces wyłączania systemu

  • void kernel_halt(void) // która kończy się na systemie w stanie zatrzymania
  • void kernel_power_off(void) // która kończy się wyłączeniem systemu
  • void kernel_restart(char *cmd) // co kończy system, aby go ponownie uruchomić

Funkcje te są bardzo krótkie i dlatego można je tutaj wkleić w całości. Ich kod najlepiej pokazuje, jakie kroki są podejmowane na drodze do zamknięcia w jądrze. (komentarze są przeze mnie i mogą nie być w 100% idealne i poprawne, sprawdź się, aby się upewnić. To prosta próba.

void kernel_halt(void)

void kernel_halt (void)
{
    // 1. krok robi:
    // a) funkcje wywołania / wywołanie zwrotne zarejestrowane do uruchomienia przy ponownym uruchomieniu / zamknięciu
    // b) ustaw system_sate na SYSTEM_HALT
    // c) zatrzymać interakcję userspacetool
    // d) wywołaj funkcję device_shutdown ()
    kernel_shutdown_prepare (SYSTEM_HALT);

    // Drugi krok: Myślę, że jest to głównie konieczność w przypadku systemów z wieloma procesorami
    migrate_to_reboot_cpu ();

    // trzeci krok:
    // syscore_shutdown - Wykonaj wszystkie zarejestrowane wywołania zwrotne zamknięcia systemu 
    syscore_shutdown ();

    // 4 wiadomości
    pr_emerg („System zatrzymany \ n”);
    kmsg_dump (KMSG_DUMP_HALT);

    // 5. kod specyficzny dla arch. Połączenia hp
    machine_halt ();
}

cała sprawa jest inicjowana przez sys_rebootwywołanie systemowe, które, biorąc pod uwagę, że nie tylko uruchamia się ponownie, ale także zamyka, nie jest bezpośrednią rzeczą do połączenia się z procesem zamykania.

ludzkośćANDpeace
źródło