Czy jądro ma funkcję main ()? [Zamknięte]

52

Uczę się sterowników urządzeń i programowania jądra. Według książki Jonathana Corbeta main()w sterownikach urządzeń nie ma żadnej funkcji.

Więc mam dwa pytania:

  • Dlaczego nie potrzebujemy main()funkcji w sterownikach urządzeń?
  • Czy samo jądro ma jakąś main()funkcję?

Czy ktoś może mi to wyjaśnić?

ktoś
źródło
1
Zapytany również przez tego samego użytkownika tutaj: stackoverflow.com/q/18266063/827263
Keith Thompson
@KeithThompson ... Tak ... Tylko dlatego, że nie dostałem odpowiedzi, czego chcę, więc zapytałem tutaj.
ktoś
@Shadur ... w każdym razie jest już blisko do zamknięcia ... I nie mam uprawnień do migrowania tego ...
ktoś
To powinno być zamknięte na odwrót, ten ma znacznie więcej wyświetleń :-)
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Odpowiedzi:

82

W programach kosmicznych użytkownika main()jest punktem wejścia do programu, który jest wywoływany przez kod inicjujący libc podczas wykonywania pliku binarnego. Kod jądra nie ma luksusu polegać na libc, ponieważ sam libc opiera się na interfejsie syscall jądra do alokacji pamięci, we / wy, zarządzania procesami itp.

To powiedziawszy, odpowiednikiem main()kodu w jądrze jest start_kernel(), który jest wywoływany przez bootloader po załadowaniu obrazu jądra, dekompresuje go do pamięci i konfiguruje niezbędny sprzęt i stronicowanie pamięci. start_kernel()wykonuje większość konfiguracji systemu i ostatecznie uruchamia proces inicjowania.

Punktem wejścia do modułów jądra systemu Linux jest funkcja init, która jest rejestrowana w jądrze przez wywołanie module_init()makra. Zarejestrowana funkcja inicjująca moduł jest następnie wywoływana przez kod jądra poprzez do_initcalls()funkcję podczas uruchamiania jądra.

Thomas Nyman
źródło
11
Dziękujemy za rozpoznanie prawdziwego celu mainmetody w C. (Jest to zbyt powszechnie uznawane błędne przekonanie, że system operacyjny wykonuje bezpośrednie wywołanie main, co nie jest przypadkiem, a tym bardziej w przypadku np. C ++.) I ' d, dam ci jeszcze jedną opinię, gdybym tylko mógł.
CVn
1
@Thomas ... Dzięki za tę doskonałą odpowiedź ....
ktoś
17

Jądro nie ma mainfunkcji. mainjest koncepcją języka C. Jądro jest napisane w C i asemblerze. Kod wejścia jądra jest zapisywany przez asembler.

Sekwencja rozruchowa jest zorganizowana w następujący sposób:

  1. BIOS zwykle ładuje moduł ładujący z urządzenia blokującego rozruch. Popularnym programem ładującym jest teraz grub.
  2. Grub ładuje obraz jądra do pamięci RAM, możliwe przy użyciu początkowego urządzenia root ( initrd). Następnie wykonywany jest kod pod jakimś adresem.
  3. Obraz jądra zawiera niektóre moduły jądra, na przykład: moduły systemu plików, sterowniki urządzeń. Obraz jądra używa modułu systemu plików do montowania głównego systemu plików. Teraz jądro może ładować i uruchamiać wszystkie moduły jądra z dysku.
  4. Jądro uruchamia zadania inicjalizacyjne. Na przykład: przejdź przez magistralę PCI i znajdź wszystkie urządzenia PCI, zainicjuj wszystkie sterowniki urządzeń.
  5. W końcu jądro tworzy proces 0 i proces 1 ( initproces), przełącza kontekst CPU z pierścienia 0 na pierścień 3 i rozpoczyna proces inicjowania (identyfikator procesu to 1). Teraz rozruch jądra jest zakończony!
  6. initProgram uruchamia wszystkie skrypty startowe. Wszystkie usługi są uruchomione. Nazywa się Shell. Użytkownicy mogą się zalogować.

Ta mainfunkcja jest funkcją C. Właściwie główną metodą nie jest punkt wejścia programów C. Środowisko wykonawcze C wywołuje wcześniej wiele funkcji main. GCC ma rozszerzoną funkcję: konstruktory. Funkcje zadeklarowane jako „konstruktor” są wywoływane wcześniej main.

Na przykład:

/* This should not be used directly. Use block_init etc. instead. */ 
#define module_init(function, type) \
    static void _attribute__((constructor)) do_qemu_init ## function(void) { \
    register_module_init(function, type); \
} 

To makro pochodzi z projektu qemu.

Edward Shen
źródło
Główną metodą jest metoda ac. Właściwie główną metodą nie jest wpisanie programu c. Środowisko wykonawcze wywołało wiele metod przed metodą główną.
Edward Shen
bios zwykle ładuje moduł ładujący, a ten moduł ładujący ładuje obraz jądra (i ewentualnie initrd). Kod jądra znajduje się na obrazie jądra, a nie initrd
Stéphane Chazelas
GCC ma rozszerzoną funkcję: konstruktor. Deklaracja metody „konstruktor” jest wywoływana przed metodą główną. Na przykład: / * Nie należy tego używać bezpośrednio. Zamiast tego użyj block_init itp. * / #define module_init (funkcja, typ) \ static void _attribute __ ((konstruktor)) do_qemu_init ## function (void) {\ register_module_init (funkcja, typ); \}
Edward Shen
1
initrd.img NIE JEST obraz jądra. Jest to zestaw modułów ładowanych przez jądro podczas rozruchu. Obrazy jądra zwykle mają nazwy zaczynające się od „vmlinuz”, ale różnią się od dystrybucji do dystrybucji.
goldilocks,
3
Ta odpowiedź jest pełna „wszystko jest PC / Linux / i86” i uruchamia się w ten sposób, a jądro jest w ten sposób ... Dlaczego wszyscy myślą, że to jedyny możliwy sposób na świecie?
Jens,
9

W arch / x86 / boot / main.c znajduje się np. Funkcja main () służąca do przygotowania systemu do przejścia z trybu rzeczywistego do chronionego, ale inne architektury nie mają takiego kodu. Jest ładny przegląd tego, jak działa uruchamianie jądra Linux 2.6.x na platformie x86. Naprawdę warto to przeczytać.

Zgodnie z dokumentem HOWTO do tworzenia jądra Linuksa, jądro Linuksa jest

wolnostojące środowisko C, bez polegania na standardowej bibliotece C, więc niektóre części standardu C nie są obsługiwane.

co zgodnie z normą C BTW to oznacza

Zdefiniowane jest wdrożenie, czy program w środowisku wolnostojącym jest wymagany do zdefiniowania funkcji „głównej”.

dsmsk80
źródło