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);

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).


+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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.