Dlaczego potrzebuję initramfs?

17

Dowiedziałem się, że jeśli wybiorę jffslub sdjako system plików (i nie initramfs), rozmiar jądra będzie bardzo mały (1,4 MB w porównaniu z tym, initramfsktóry wynosi 3,4 MB). Oznacza to, że initramfszajmuje dużo miejsca. Więc jeśli mogę, całkowicie go usunę, a więc będę miał bardzo małe jądro, czego chcę.

Podstawowe pytanie, które pojawia się w moim umyśle, brzmi: dlaczego potrzebuję initramfs? Czy jądro Linuksa nie może zostać uruchomione bez początkowego systemu plików?

Moja aplikacja końcowa wykona tylko obliczenia i komunikację - w ogóle nie będzie pamięci. Więc system operacyjny bez systemu plików ma sens - przynajmniej dla mojej aplikacji.

gpuguy
źródło
2
Nie możesz obejść się bez initramfs. Można to zrobić bez dodatkowego pliku initramfs, ale niezależnie od tego, co robisz, jądro zawiera swoje własne puste lub nie. Więc nie rozumiem twojego pytania - o jakiej dystrybucji mówisz? Jak budujesz jądro? Czy możesz podać plik .config jądra? To są bardzo ważne. Podejrzewam, że twoja dystrybucja kompiluje jego initramfs bezpośrednio do jądra - i dlatego wypełnia puste puste initramfs, które zawiera - ale nie wiem na podstawie dostarczonych informacji.
mikeserv
2
@ mikeserv, oczywiście wbudowane, ale puste / nieużywane initramfs się nie liczą.
psusi
Cóż, @psusi dokumentacja jądra się nie zgadza. I jestem tak nieugięty, ponieważ nie musi być żadnej tajemnicy - to jest po prostu /root- to wszystko. Jedyną rzeczą, którą robi inaczej, jest switch_rootjednak to, że pod warunkiem zachowania odpowiednich środków ostrożności przy niektórych załadowanych modułach jądra, można to zrobić w dowolnym momencie. Initramfs jest niczym więcej niż obrazem dysku - wypełnionym lub nie, jest tam. I nigdy nie jesteś bez niego - w końcu to Twój korzeń. Myślę, że nie powinna to być tajemnica i nie podoba mi się niepotrzebne zamieszanie wokół niej.
mikeserv
2
@ mikeserv, nie, / root to katalog domowy użytkownika root. Rootfs to /, który następnie ma zamontowany na nim prawdziwy root. Kłócisz się tylko o semantykę. Na potrzeby tej dyskusji brak initramfs oznacza brak pliku na dysku, który program ładujący musi załadować i przekazać do jądra.
psusi
To prawda, użyłem / root tylko dla jasności, ale dam ci to. Ale nie, nie są one semantyką, są podstawową mechaniką jądra Linuksa. To są podstawowe rzeczy. Spróbujmy tylko je naprawić.
mikeserv

Odpowiedzi:

12

Wzrost rozmiaru posiadania initramfs nie jest spowodowany sterownikiem ramfs (to tylko kilka KB, i tak jest potrzebne do innych rzeczy), ale samym initramfs. Initramfs zawiera programy niezbędne do złożenia i zamontowania prawdziwego systemu plików root.

Initramfs znacznie ułatwia, aw niektórych przypadkach umożliwia (np. Szyfrowanie /), uruchomienie systemu. Zdecydowanie zaleca się trzymanie go na sprzęcie typu PC z dużą ilością urządzeń peryferyjnych z możliwością podłączenia podczas pracy. Z drugiej strony sensowne jest uruchamianie urządzenia osadzonego bez żadnych initramfs, z jądrem obsługującym konkretną konfigurację sprzętową, dla której został zbudowany.

Jądro oczywiście wymaga rozruchu do systemu plików: musi istnieć sposób załadowania dowolnej aplikacji, którą chcesz uruchomić. Jeśli nie zamierzasz nic uruchamiać, równie dobrze możesz wyłączyć maszynę.

Jeśli nie chcesz używać initramfs, po prostu powiedz swojemu programowi ładującemu, aby go nie przekazywał. Oczywiście nie dołączaj też jednego z danych wyjściowych kompilacji jądra - jak to się dzieje, jeśli w ogóle zależy od architektury i programu ładującego: na przykład vmlinuxi bzImagenie włączaj initramfs (odpowiednio jądro surowe i skompresowane ), ale uImage(dla U-Boot) pakuje zarówno jądro, jak i initramfs, jeśli taki istnieje.

(Technicznie, jak zauważa mikeserv , zawsze jest initramfs - ale domyślnie jest to puste, 134-bajtowe archiwum. To, co widzisz i czego chcesz się pozbyć, to „prawdziwe”, niepuste initramfy utworzone przez proces kompilacji i zawierający narzędzia, które są następnie używane do montowania głównego systemu plików).

Pamiętaj, że initramfs może być rozsądnym sposobem na stworzenie systemu pojedynczej aplikacji bez trwałych danych: włóż całą aplikację do initramfs, uruchom ją i zachowaj. Ułatwia to uporządkowanie trwałego magazynu lub obrazu rozruchowego (wszystko czego potrzebujesz to jądro i initramfs, które można spakować). Istnieją jednak wady tego podejścia: wszystkie dane w initramfs będą trwale przechowywane w pamięci RAM i nie można łatwo modyfikować plików w obrazie rozruchowym, należy odbudować archiwum.

Gilles „SO- przestań być zły”
źródło
Jeśli używasz jądra Linuksa 2.6 lub nowszego, masz initramfs. To, czy używasz dodatkowego obrazu initramfs, jak jest zwyczajowo, to inna sprawa, ale initramfs nie jest opcjonalny.
mikeserv
2
@mikeserv Masz jeden, tak. Ale pusty initramfs to orzeszki ziemne. Nie trzeba go używać (co wymaga, aby zawierał wystarczającą liczbę programów do zamontowania prawdziwego katalogu głównego, co zwiększa rozmiar w nieunikniony sposób w typowym systemie osadzonym).
Gilles „SO- przestań być zły”
W każdym razie obowiązkowe orzeszki ziemne. I nie wiem, kiedy powiedziałem inaczej! Pytający żądał informacji, jak usunąć go jako system plików - co nie jest możliwe.
mikeserv
I tak, trzeba go użyć - bez initramfs nie ma roota. Zawsze.
mikeserv
8

Z BAEL :

Jedynym celem initramfs jest zamontowanie głównego systemu plików. Initramfs to kompletny zestaw katalogów, które można znaleźć w normalnym systemie plików root. Jest on zawarty w jednym archiwum CPIO i skompresowany za pomocą jednego z kilku algorytmów kompresji.

...

Istnieją tylko cztery główne powody, dla których warto mieć initramfs w środowisku LFS: ładowanie rootfów z sieci, ładowanie z woluminu logicznego LVM, posiadanie zaszyfrowanych rootfsów, w których wymagane jest hasło, lub dla wygody określenia rootfów jako ETYKIETA lub UUID. Wszystko inne zwykle oznacza, że ​​jądro nie zostało poprawnie skonfigurowane.

...

W przypadku większości dystrybucji moduły jądra są największym powodem posiadania initramfs. W ogólnej dystrybucji istnieje wiele niewiadomych, takich jak typy systemów plików i układy dysków. W pewnym sensie jest to przeciwieństwo LFS, w którym znane są możliwości i układ systemu, a niestandardowe jądro jest zwykle budowane. W tej sytuacji initramfs jest rzadko potrzebny.

Inne źródło www.kernel.org

Oprócz tego istnieje wiele systemów Linux, które lubią routery, które nie używają initramfs.


źródło
1

Potrzebujesz initramfs do bardziej skomplikowanych konfiguracji, takich jak rozruch sieciowy, lvm lub raid, ponieważ wymagają one narzędzi trybu użytkownika do skonfigurowania dostępu do root fs. W przypadku prostej, konwencjonalnej partycji na dysku, o ile masz wbudowane sterowniki dyskowe w jądrze i określasz argument root według ścieżki urządzenia zamiast UUID, możesz zrobić to bez initramfs. Oczywiście ścieżka urządzenia może ulec zmianie, w zależności od podłączonych urządzeń typu plug and play (tj. Usb), a nawet po prostu losowych różnic czasowych, dlatego prawie wszyscy używają uuids i initramfs dla niezawodności.

psusi
źródło
To również jest nieprawidłowe.
mikeserv
6
@mikeserv, twój komentarz jest bezużyteczny. Jeśli chcesz to twierdzić, musisz wyjaśnić, dlaczego.
psusi
Zrobiłem, a raczej dokumentację jądra składającą się na około 99% mojej odpowiedzi.
mikeserv
@ Mikeserv, jest poprawne. Używam Linuksa Gentoo od lat bez initramfs.
Tim
1

To stare pytanie, ale nadal nie wydaje się, że ma akceptowaną odpowiedź, więc wyrzucę to tutaj (nie jestem tutaj ekspertem, staram się to sobie wymyślić).

Od https://www.kernel.org/doc/Documentation/early-userspace/README (do samego końca, który mówi, że nie był aktualizowany od 2004 r.)

Jądro ma obecnie 3 sposoby montowania głównego systemu plików:

a) wszystkie wymagane sterowniki urządzeń i systemów plików wkompilowane w jądro, bez initrd. init / main.c: init () wywoła przygotowanie_nazwa_przestrzeni () w celu zamontowania końcowego systemu plików root, na podstawie opcji root = i opcjonalnego init = w celu uruchomienia innego pliku binarnego init niż wymieniony na końcu init / main.c: init ().

b) niektóre sterowniki urządzeń i systemów plików zbudowane jako moduły i zapisane w initrd. Plik initrd musi zawierać binarny plik „/ linuxrc”, który powinien ładować te moduły sterowników. Możliwe jest również zamontowanie końcowego systemu plików za pomocą linuxrc i użycie syscall pivot_root. Initrd jest montowany i wykonywany za pomocą prepar_namespace ().

c) za pomocą initramfs. Wywołanie metody prepar_namespace () musi zostać pominięte. Oznacza to, że plik binarny musi wykonać całą pracę. Wspomniany plik binarny może być przechowywany w initramfs poprzez modyfikację usr / gen_init_cpio.c lub poprzez nowy format initrd, archiwum cpio. Musi się nazywać „/ init”. Ten plik binarny jest odpowiedzialny za wykonanie wszystkich czynności, które zrobiłaby prepar_namespace ().

Aby zachować zgodność wsteczną, plik binarny / init będzie działał tylko wtedy, gdy będzie pochodził z archiwum cpio initramfs. Jeśli tak nie jest, init / main.c: init () uruchomi prepar_namespace (), aby zamontować końcowy katalog główny i wykonać jeden ze wstępnie zdefiniowanych plików binarnych init.

Co do tego, co jest warte, uważam, że urządzenia / dystrybucje takie jak Raspberry Pi itp. Nie używają initramfs; w niektórych przypadkach jądro znajduje się na partycji głównej (montowanej przez bootloader, który ma wymagane moduły fs). W innych przypadkach, gdy jądro znajduje się np. na /bootpartycji, dostęp do initramfs na tej samej partycji można uzyskać bezpośrednio przed zamontowaniem rootfs jak inni stwierdzili.

W niektórych przypadkach initramfs mogą być wbudowane w ten sam plik co jądro, ale nie zawsze tak jest. (a) wydaje się dość wyraźnie stwierdzać, że w niektórych przypadkach initramfs nie jest konieczne.

thom_nic
źródło
0

Uważam, że następujące wyjaśnienie bardziej jasne,

initramfsto główny system plików, który jest osadzony w jądrze i ładowany na wczesnym etapie procesu rozruchu. Jest następcą initrd. Zapewnia wczesną przestrzeń użytkownika, która może robić rzeczy, których jądro nie może łatwo zrobić samodzielnie podczas procesu rozruchu.

Korzystanie z initramfs jest opcjonalne. Domyślnie jądro inicjuje sprzęt za pomocą wbudowanych sterowników, montuje określoną partycję root, ładuje system init zainstalowanej dystrybucji Linuksa. Następnie system init ładuje dodatkowe moduły i uruchamia usługi, aż w końcu pozwoli ci się zalogować. Jest to dobre zachowanie domyślne i wystarczające dla wielu użytkowników. initramfs jest dla użytkowników z zaawansowanymi wymaganiami; dla użytkowników, którzy muszą robić rzeczy jak najwcześniej, nawet przed zamontowaniem partycji root.

Oto kilka przykładów tego, co możesz zrobić z initramfs:

  • Zamontuj partycję root (dla partycji zaszyfrowanych, logicznych i innych);
  • Zapewnij minimalistyczną powłokę ratunkową (jeśli coś pójdzie nie tak);
  • Dostosuj proces rozruchu (np. Wydrukuj wiadomość powitalną, powitalny rozruch itp.);
  • Załaduj moduły (np. Sterowniki innych producentów);
  • Wszystko, czego jądro nie może zrobić (o ile można to zrobić w przestrzeni użytkownika, np. Wykonując polecenia). Jeśli nie masz zaawansowanych wymagań, nie potrzebujesz initramfs.
Sufiyan Ghori
źródło
-1

Bez względu na to, co robisz, masz initramfs. Bez tego nie można się obejść - jest to jedyny narzucony system plików. Z kernel.org :

Co to jest rootfs?

Rootfsjest specjalną instancją ramfs(lub tmpfs, jeśli jest włączona), która zawsze występuje w systemach 2.6. Nie można odmontowaćrootfs z mniej więcej tego samego powodu, dla którego nie można zabić procesu inicjowania; zamiast specjalnego kodu do sprawdzania i obsługi pustej listy, jądro jest mniejsze i prostsze, aby upewnić się, że niektóre listy nie będą puste.

Większość systemów po prostu montuje inny system plików rootfsi ignoruje go. Ilość miejsca, które zajmuje pusta instancja ramfs, jest niewielka.

Jeśli * CONFIG_TMPFS * jest włączony, rootfsużyje tmpfszamiast ramfsniego domyślnie. Aby wymusić ramfs, dodaj "rootfstype=ramfs"do wiersza poleceń jądra.

Co to jest initramfs?

Wszystkie jądra Linuksa 2.6 zawierają"cpio"archiwum w formaciegzip, do którego jest wyodrębniane rootfspo uruchomieniu jądra. Po rozpakowaniu jądro sprawdza, czyrootfszawiera plik"init" , a jeśli tak, to wykonuje go jako PID 1. Jeśli zostanie znaleziony,initprocestenjest odpowiedzialny za podniesienie systemu do końca, w tym zlokalizowanie i zamontowanie prawdziwego urządzenia root ( Jeśli w ogóle). Jeślipowyodrębnieniuosadzonegoarchiwumrootfsnie zawierainitprogramucpio, jądro przejdzie do starszego kodu w celu zlokalizowania i zamontowania partycji głównej, a następnie wykona jakiś wariant/sbin/initz tego.

Wszystko to różni się od starego initrd na kilka sposobów:

  • Stary initrd był zawsze osobnym plikiem, podczas gdy archiwum initramfs jest połączone z obrazem jądra Linuksa. (Katalog linux - * / usr poświęcony jest generowaniu tego archiwum podczas kompilacji).

  • Stary plik initrd był obrazem systemu plików spakowanym gzipem (w pewnym formacie pliku, takim jak ext2, który wymagał sterownika wbudowanego w jądro), podczas gdy nowe archiwum initramfs jest spakowanym gzip archiwum cpio (podobnie jak tar tylko prościej, patrz cpio (1) oraz Documentation / early-userspace / buffer-format.txt). Kod wyodrębniania cpio jądra jest nie tylko bardzo mały, ale także __init tekst i dane, które można usunąć podczas procesu uruchamiania.

  • Program uruchamiany przez stary initrd (który nazywał się / initrd, not / init) wykonał trochę instalacji, a następnie wrócił do jądra, podczas gdy program init z initramfs nie powinien wrócić do jądra. (Jeśli / init musi przekazać kontrolę, może przełączyć się na / z nowym urządzeniem root i uruchomić inny program init. Zobacz narzędzie switch_root poniżej.)

  • Podczas przełączania innego urządzenia root, initrd pivot_root, a następnie podłącza ramdysk. Ale initramfs to rootfs: nie można ani rootfs przestawić_ roota, ani odmontować go. Zamiast tego usuń wszystko z rootfów, aby zwolnić miejsce (znajdź -xdev / -exec rm '{}' ';'), zamontuj rootfsy z nowym rootem (cd / newmount; mount --move. /; Chroot.), dołącz stdin / stdout / stderr do nowego / dev / console i uruchom nową init.

Ponieważ jest to wyjątkowo persnickety proces (i polega na usuwaniu poleceń przed ich uruchomieniem), pakiet klibc wprowadził program pomocniczy (utils / run_init.c), aby zrobić to wszystko za Ciebie. Większość innych pakietów (takich jak busybox) nazwała tę komendę „switch_root”.

Wypełnianie initramfs:

Proces budowania jądra 2.6 zawsze tworzy spakowane archiwum initramfs w formacie cpio i łączy je z wynikowym plikiem binarnym jądra. Domyślnie to archiwum jest puste (zużywa 134 bajty na x86).

Opcji konfiguracyjnej CONFIG_INITRAMFS_SOURCE (w Ustawieniach ogólnych w menuconfig i mieszkaniu w usr / Kconfig) można użyć do określenia źródła dla archiwum initramfs, które zostanie automatycznie włączone do wynikowego pliku binarnego. Ta opcja może wskazywać na istniejące spakowane gzip archiwum cpio, katalog zawierający pliki do zarchiwizowania lub specyfikację pliku tekstowego, na przykład w następującym przykładzie:

  dir /dev 755 0 0
  nod /dev/console 644 0 0 c 5 1
  nod /dev/loop0 644 0 0 b 7 0
  dir /bin 755 1000 1000
  slink /bin/sh busybox 777 0 0
  file /bin/busybox initramfs/busybox 755 0 0
  dir /proc 755 0 0
  dir /sys 755 0 0
  dir /mnt 755 0 0
  file /init initramfs/init.sh 755 0 0

Uruchom „usr / gen_init_cpio” (po kompilacji jądra), aby otrzymać komunikat o użytkowaniu dokumentujący powyższy format pliku.

Jedną z zalet pliku konfiguracyjnego jest to, że dostęp do konta root nie jest wymagany do ustawiania uprawnień ani tworzenia węzłów urządzeń w nowym archiwum. (Zauważ, że te dwa przykładowe wpisy „file” spodziewają się znaleźć pliki o nazwach „init.sh” i „busybox” w katalogu o nazwie „initramfs”, w katalogu linux-2.6. *. Aby uzyskać więcej informacji, zobacz Dokumentacja / wczesna przestrzeń użytkownika / README więcej szczegółów.)

Jądro nie zależy od zewnętrznych narzędzi CPIO. Jeśli podasz katalog zamiast pliku konfiguracyjnego, infrastruktura kompilacji jądra utworzy plik konfiguracyjny z tego katalogu (usr / Makefile wywołuje skrypty / gen_initramfs_list.sh), i przechodzi do spakowania tego katalogu za pomocą pliku konfiguracyjnego (poprzez przekazanie go do usr / gen_init_cpio, który jest tworzony z usr / gen_init_cpio.c). Kod tworzenia cpio jądra w czasie kompilacji jest całkowicie samowystarczalny, a ekstraktor czasu rozruchu jądra jest (oczywiście) samowystarczalny.

mikeserv
źródło
1
Możesz uruchomić bez initramfs. Twoja odpowiedź wyjaśnia zalety programu initramfs, ale nie dotyczy to typowych systemów osadzonych, a nawet na komputerach stacjonarnych lub serwerach, na których zalecany jest program initramfs, nie jest obowiązkowy.
Gilles „SO- przestań być zły”
@Gilles - no you cant. Niezależnie od tego, co robisz, masz initramfs. Jest wkompilowany w jądro - teraz twoje jądro, moje jądro, wszystkie nasze jądra. Przeczytaj dokumentację jądra - cały mój post został skopiowany i wklej. Jesteś w błędzie Jak można zakwestionować oficjalną dokumentację?
mikeserv
1
Nie kwestionuję oficjalnej dokumentacji, kwestionuję wnioski, które z niej wyciągasz. Czytasz dokumentację wyjaśniającą, jak korzystać z initramfs. Nigdzie nie stwierdzono, że należy użyć initramfs.
Gilles „SO- przestań być zły”
@Gilles Jeśli to nie wystarczy: „Proces kompilacji jądra 2.6 zawsze tworzy archiwum initramfs w formacie gzipped cpio i łączy je z wynikowym plikiem binarnym jądra. Domyślnie to archiwum jest puste (zużywa 134 bajty na x86) .... " Potrafię zrobić to lepiej. Powyżej było 2 lub 3 minuty wyszukiwania w Internecie.
mikeserv
3
Przeczytałem dokumentację. Robię to na życie. To nie jest kwestia opinii. Zawsze istnieje initramfs, ale niekoniecznie jest używany do uruchamiania. Nie mogę znaleźć porządnego wyjaśnienia struktury jądra dla tego przypadku, prawdopodobnie dlatego, że jest to klasyczny przypadek, o którym uważa się, że nie uzasadnia wyjaśnienia. Główna logika jest w do_mounts.cszczególności prepare_namespace, w której saved_root_namejest zapełniany root=argumentem wiersza poleceń.
Gilles „SO- przestań być zły”