W jaki sposób Linux ładuje obraz „initrd”?


13

Próbowałem zrozumieć proces uruchamiania, ale jest tylko jedna rzecz, która przechodzi mi przez głowę ...

Zaraz po uruchomieniu jądra Linux i podłączeniu głównego systemu plików (/) można uruchomić programy i zintegrować kolejne moduły jądra w celu zapewnienia dodatkowych funkcji. Aby zamontować główny system plików, muszą być spełnione określone warunki. Jądro potrzebuje odpowiednich sterowników, aby uzyskać dostęp do urządzenia, na którym znajduje się główny system plików (szczególnie sterowniki SCSI). Jądro musi również zawierać kod potrzebny do odczytania systemu plików (ext2, reiserfs, romfs itp.). Możliwe jest również, że główny system plików jest już zaszyfrowany. W takim przypadku do zamontowania systemu plików potrzebne jest hasło.

Początkowy ramdysk (zwany także initdisk lub initrd) rozwiązuje dokładnie problemy opisane powyżej. Jądro Linux zapewnia opcję załadowania małego systemu plików na dysk RAM i uruchomienia tam programów przed zamontowaniem głównego systemu plików. Ładowanie initrd jest obsługiwane przez moduł ładujący (GRUB, LILO itp.). Programy ładujące potrzebują tylko procedur systemu BIOS, aby załadować dane z nośnika rozruchowego. Jeśli moduł ładujący jest w stanie załadować jądro, może także załadować początkowy ramdysk. Specjalne sterowniki nie są wymagane.

Jeśli / boot nie jest inną partycją, ale jest obecny na partycji /, to czy moduł ładujący nie powinien wymagać sterowników SCSI, aby uzyskać dostęp do obrazu „initrd” i obrazu jądra? Jeśli masz bezpośredni dostęp do obrazów, to dlaczego dokładnie potrzebujemy sterowników SCSI?

Odpowiedzi:


20

Nighpher, postaram się odpowiedzieć na twoje pytanie, ale w celu uzyskania pełniejszego opisu procesu rozruchu, przeczytaj artykuł IBM .

Ok, zakładam, że używasz GRUB lub GRUB2 jako bootloadera dla wyjaśnienia. Po pierwsze, kiedy BIOS uzyskuje dostęp do dysku w celu załadowania bootloadera, korzysta z wbudowanych procedur dostępu do dysku, które są przechowywane w słynnym 13-godzinnym przerwie. Program ładujący (i jądro w fazie instalacji) korzysta z tych procedur podczas uzyskiwania dostępu do dysku. Należy pamiętać, że BIOS działa w trybie procesora w trybie rzeczywistym (16 bitów), dlatego nie może adresować więcej niż 2 ^ 20 bajtów pamięci RAM (2 ^ 20 nie 2 ^ 16, ponieważ każdy adres w trybie rzeczywistym składa się z adresu segmentu * 16 + przesunięcia , gdzie zarówno adres segmentu, jak i przesunięcie są 16-bitowe, patrz http://en.wikipedia.org/wiki/X86_memory_segmentation ). W związku z tym te procedury nie mogą uzyskać dostępu do więcej niż 1 MiB pamięci RAM, co jest ścisłym ograniczeniem i poważną niedogodnością.

BIOS ładuje kod bootloadera bezpośrednio z MBR - pierwsze 512 bajtów dysku i wykonuje go. Jeśli używasz GRUB, ten kod to GRUB etap 1. Ten kod ładuje GRUB etap 1.5, który znajduje się albo w pierwszych 32 KiB miejsca na dysku, zwanym regionem zgodności z DOS, albo ze stałego adresu systemu plików. Aby to zrobić, nie musi rozumieć systemu plików, ponieważ nawet etap 1.5 znajduje się w systemie plików, jest to „surowy” kod i można go bezpośrednio załadować do pamięci RAM i wykonać: http://www.pixelbeat.org/ docs / disk / . Ładowanie etapu 1.5 z dysku do pamięci RAM wykorzystuje procedury dostępu do dysku BIOS.

wprowadź opis zdjęcia tutaj

Stage1.5 zawiera narzędzia systemu plików, dzięki czemu może czytać stage2 z systemu plików (cóż, nadal używa BIOS 13h do odczytu z dysku do pamięci RAM, ale teraz może odszyfrować informacje o systemie plików o i-węzłach itp. I uzyskać surowy kod z dysk). Starsze BIOSy mogą nie być w stanie uzyskać dostępu do całego HD z powodu ograniczeń w trybie adresowania dysku - mogą korzystać z systemu Cylinder-Head-Sector, nie mogąc rozwiązać więcej niż pierwszych 8 GiB miejsca na dysku: http: //en.wikipedia. org / wiki / Sektor cylindra .

Stage2 ładuje jądro do pamięci RAM (ponownie, używając narzędzi dyskowych BIOS). Jeśli jest to jądro 2.6+, ma również skompilowane initramfs, więc nie trzeba go ładować. Jeśli jest to starsze jądro, bootloader ładuje również samodzielny obraz initrd do pamięci, aby jądro mogło go zamontować i uzyskać sterowniki do montowania prawdziwego systemu plików z dysku.

Problem polega na tym, że jądro (i ramdysk) ważą więcej niż 1 MiB, dlatego aby załadować je do pamięci RAM, należy załadować jądro do pierwszego 1 MiB, a następnie przejść do trybu chronionego (32-bitowy), przenieść załadowane jądro do wysokiej pamięci (wolne pierwszy 1 MiB dla trybu rzeczywistego), następnie ponownie wróć do trybu rzeczywistego (16 bitów), przenieś ramdysk z dysku do pierwszego 1 MiB (jeśli jest to osobne jądro initrd i starsze jądro), prawdopodobnie przełącz się ponownie w tryb chroniony (32-bitowy), umieść go tam, gdzie należy, ewentualnie wróć do trybu rzeczywistego (lub nie: /programming/4821911/does-grub-switch-to-protected-mode ) i uruchom kod jądra. Ostrzeżenie: nie jestem całkowicie pewien dokładności i dokładności tej części opisu.

Teraz, kiedy w końcu uruchomisz jądro, już je ładujesz i ramdysk jest ładowany do pamięci RAM przez bootloader , więc jądro może korzystać z narzędzi dyskowych z ramdysku, aby zamontować prawdziwy system plików root i przestawić do niego root. Sterowniki ramfs są obecne w jądrze, więc może oczywiście zrozumieć zawartość initramfs.


Czy bootlader nie może po prostu załadować jądra w porcje, zamiast skakać w tryb chroniony? A jaka jest potrzeba uwolnienia 1 MB .. (Przepraszam .. nie mogłem tego zrozumieć ...)
rpthms

Konieczność uwolnienia pierwszego 1MiB jest następująca: bootloader może uzyskać dostęp do twojego dysku twardego tylko w trybie rzeczywistym, ponieważ uzyskuje do niego dostęp za pomocą narzędzi BIOS, które są w trybie rzeczywistym (działają na argumentach 16-bitowych i używają operacji 16-bitowych). Tryb rzeczywisty po prostu nie widzi żadnej pamięci RAM oprócz pierwszego 1 MiB. Ale musisz załadować jądro + initramfs do pamięci RAM, a one zajmują ~ 5 MiB miejsca w pamięci RAM. Te narzędzia BIOS po prostu nie będą w stanie wycisnąć 5 MiB do pierwszego 1 MiB. Bootloader musi więc skopiować je z dysku do pierwszego 1 MiB, a następnie przejść do trybu chronionego i przenieść je z pierwszej 1 MB pamięci RAM na wyższą pamięć RAM. Czy to jest teraz jaśniejsze? :)
Boris Burkov,

1
Cały etap 1 / 1,5 / 2 to gruba spuścizna.
psusi

1
@CMCDragonkai Tak, program ładujący stage2 znajduje się w systemie plików (czyli na /bootpartycji). Jądro nie jest w tym momencie ładowane - chodzi o stage1.5 gruba, który uzyskuje dostęp do stage2 w /bootsystemie plików (np. W /boot/grubpliku) za pośrednictwem minimalistycznych sterowników systemu plików. Jądro będzie również mogło czytać z /bootpartycji, ale stanie się to później, po wykonaniu kodu grub2 i załadowaniu jądra oraz po odczytaniu przez initramfs jądra. Czy mówisz init.sho initramfs? Znajduje się on na /bootpartycji dysku twardego, następnie etap2 grub umieszcza go w pamięci RAM, a jądro odczytuje go z pamięci RAM.
Boris Burkov,

1
Initrd musiał być osobnym plikiem. Nowsze initramfs można połączyć z jądrem, ale nie musi tak być - może być również załadowane jako bootloader jako osobny plik. Ponieważ plik initramfs jest zdefiniowany jako sekwencja archiwów CPIO, niektóre programy ładujące (np. IPXE) pozwalają nawet na wiele plików initramfs, które będą ładowane jeden po drugim do pamięci. Ponadto niektóre dystrybucje Linuksa używają nazw plików w stylu initrd dla kompatybilności wstecznej, chociaż faktyczną technologią jest teraz initramfs.
telcoM

1

Uważam, że sprowadza się to do tego, jakie funkcje obsługuje dany program ładujący. Na przykład. nie musi znać konkretnego systemu plików na połączonej partycji (boot + root). W takim przypadku wystarczy utworzyć oddzielną partycję rozruchową pod warunkiem, że będzie ona działać z programem ładującym, a wszelkie inne złożoności sposobu montowania partycji głównej pozostaną w jądrze i obrazie initrd uruchomionym z partycji rozruchowej. Bootloader wie, jak uzyskać dostęp do urządzeń SCSI (i innych urządzeń, w zależności od używanego bootloadera), używając własnych sterowników lub procedur BIOS. Ponadto umie odczytywać niektóre systemy plików itp.

Zastanów się np. Sposób uruchamiania systemu UEFI, w którym oprogramowanie układowe UEFI już wie, jak uzyskać dostęp do partycji EFI, odczytać ją i załadować stamtąd jądro Linuksa bez potrzeby pośredniego programu ładującego. W takim przypadku obraz linux żyje oddzielony od partycji głównej, a oprogramowanie układowe UEFI nie musi znać wszystkich egzotycznych systemów plików, aby uzyskać do niego dostęp. Uważam, że oddzielenie obrazów „rozruchowych” od partycji „root” ma sens. Jeśli nie, to jest to konieczne przy konfigurowaniu szyfrowania systemu plików root.


0

Dla przypomnienia, jeśli bootloader nie ładuje initrd, warto przetestować inny bootloader; Właśnie wpadł sytuacji jak ta , gdy LILO zignorowane prawidłowo podano initrd średniej wielkości (<4Mb; pojedyncze głównego systemu plików ext4 na SATA SSD; GPT) i GRUB 2.00 udało.

Proces rozruchu zakończył się szybko typowym

RAMDISK: Couldn't find valid RAM disk image starting at 0.
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(8,3)
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.