Jakie są minimalne aplikacje systemu plików root, aby w pełni uruchomić system Linux?


17

To pytanie o aplikacje do przestrzeni użytkownika, ale wysłuchaj mnie!

Trzy „aplikacje”, że tak powiem, są wymagane do uruchomienia funkcjonalnej dystrybucji Linuksa:

  1. Bootloader - Dla osadzonych zwykle jest to U-Boot, choć nie jest to trudne wymaganie.

  2. Jądro - to całkiem proste.

  3. Zrootowany system plików - nie można bez niego uruchomić powłoki. Zawiera system plików, do którego jądro uruchamia się i gdzie initjest nazywany formą.

Moje pytanie dotyczy # 3. Jeśli ktoś chciałby zbudować bardzo minimalne rootfsy (w tym pytaniu powiedzmy, że nie ma GUI, tylko powłoka), jakie pliki / programy są wymagane do rozruchu z powłoki?


Określ minimalne. Możesz użyć tylko jednego pliku wykonywalnego z niczym innym, jak wyjaśniono na stronie: superuser.com/a/991733/128124 Tyle, że nie można go zamknąć przy każdym wyjściu ani panikować, więc potrzebujesz nieskończonej pętli lub długiego snu. Podobne pytanie: unix.stackexchange.com/questions/17122/...
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Odpowiedzi:


32

To całkowicie zależy od tego, jakie usługi chcesz mieć na swoim urządzeniu.

Programy

Możesz uruchomić Linuksa bezpośrednio w powłoce . Nie jest bardzo przydatny w produkcji - kto chciałby po prostu mieć tam powłokę - ale jest użyteczny jako mechanizm interwencji, gdy masz interaktywny bootloader: przejdź init=/bin/shdo wiersza poleceń jądra. Wszystkie systemy Linux (i wszystkie systemy uniksowe) mają powłokę w stylu Bourne / POSIX /bin/sh.

Będziesz potrzebował zestawu narzędzi powłoki . BusyBox jest bardzo powszechnym wyborem; zawiera skorupę i wspólnych narzędzi do pliku tekstowego i manipulacji ( cp, grep...), konfigurację sieci ( ping, ifconfig...), manipulowanie procesem ( ps, nice...), i różne inne narzędzia systemowe ( fdisk, mount, syslogd, ...). BusyBox jest niezwykle konfigurowalny: możesz wybrać narzędzia, które chcesz, a nawet poszczególne funkcje w czasie kompilacji, aby uzyskać właściwy kompromis w zakresie rozmiaru / funkcjonalności aplikacji. Oprócz sh, niezbędne minimum, które tak naprawdę nie można nic zrobić bez jest mount, umounta halt, ale byłoby to nietypowe, aby nie mieć również cat, cp, mv, rm,mkdir, rmdir, ps, syncI kilka innych. BusyBox instaluje się jako pojedynczy plik binarny o nazwie busybox, z dowiązaniem symbolicznym dla każdego narzędzia.

Pierwszy proces w normalnym systemie uniksowym jest nazywany init. Jego zadaniem jest uruchomienie innych usług. BusyBox zawiera system inicjujący. Oprócz pliku initbinarnego (zwykle znajdującego się w /sbin) będziesz potrzebować jego plików konfiguracyjnych (zwykle nazywanych /etc/inittab- niektóre współczesne zastępowania init usuwają ten plik, ale nie znajdziesz ich w małym systemie osadzonym), które wskazują, jakie usługi uruchomić i kiedy. W przypadku BusyBox /etc/inittabjest opcjonalny; jeśli go brakuje, dostajesz powłokę root na konsoli, a skrypt /etc/init.d/rcS(domyślna lokalizacja) jest wykonywany podczas rozruchu.

To wszystko, czego potrzebujesz, poza programami, które sprawiają, że Twoje urządzenie robi coś pożytecznego. Na przykład na moim routerze domowym z wariantem OpenWrt jedynymi programami są BusyBox nvram(do odczytu i zmiany ustawień w pamięci NVRAM) oraz narzędzia sieciowe.

O ile wszystkie pliki wykonywalne nie są połączone statycznie, potrzebujesz dynamicznego modułu ładującego ( ld.soktóry może być wywoływany pod różnymi nazwami w zależności od wyboru biblioteki libc i architektury procesora) oraz wszystkich bibliotek dynamicznych ( /lib/lib*.sobyć może niektórych z nich /usr/lib) wymaganych przez te pliki wykonywalne.

Struktura katalogów

Filesystem Hierarchy Standard opisuje wspólną strukturę katalogów systemów Linux. Jest ukierunkowany na instalacje komputerów i serwerów: wiele z nich można pominąć w systemie wbudowanym. Oto typowe minimum.

  • /bin: programy wykonywalne (niektóre mogą być w /usr/binzamian).
  • /dev: węzły urządzeń (patrz poniżej)
  • /etc: pliki konfiguracyjne
  • /lib: biblioteki współdzielone, w tym dynamiczny moduł ładujący (chyba że wszystkie pliki wykonywalne są połączone statycznie)
  • /proc: punkt podłączenia dla systemu plików proc
  • /sbin: programy wykonywalne. Różnica /binpolega na tym, że /sbindotyczy programów, które są użyteczne tylko dla administratora systemu, ale to rozróżnienie nie ma znaczenia na urządzeniach osadzonych. Możesz zrobić /sbinsymboliczny link do /bin.
  • /mnt: przydatne w przypadku głównych systemów plików tylko do odczytu jako punktu montowania na podstawie podczas konserwacji
  • /sys: punkt montowania systemu plików sysfs
  • /tmp: lokalizacja plików tymczasowych (często tmpfsmontowanie)
  • /usr: Zawiera podkatalogi bin, liba sbin. /usristnieje dla dodatkowych plików, które nie znajdują się w głównym systemie plików. Jeśli go nie masz, możesz utworzyć /usrsymboliczne łącze do katalogu głównego.

Pliki urządzeń

Oto kilka typowych wpisów w minimalnym /dev:

  • console
  • full (pisanie do niego zawsze zgłasza „brak miejsca na urządzeniu”)
  • log(gniazdo używane przez programy do wysyłania wpisów do dziennika), jeśli syslogdodczytujesz z niego demon (np. BusyBox)
  • null (działa jak plik, który zawsze jest pusty)
  • ptmxoraz ptskatalog , jeśli chcesz używać pseudo-terminali (tj. dowolnego terminala innego niż konsola) - np. jeśli urządzenie jest podłączone do sieci i chcesz połączyć się za pomocą telnet lub ssh
  • random (zwraca losowe bajty, ryzyko zablokowania)
  • tty (zawsze oznacza terminal programu)
  • urandom (zwraca losowe bajty, nigdy nie blokuje, ale może nie być losowe na świeżo uruchomionym urządzeniu)
  • zero (zawiera nieskończoną sekwencję bajtów pustych)

Poza tym będziesz potrzebować wpisów dla swojego sprzętu (z wyjątkiem interfejsów sieciowych, które nie dostają wpisów /dev): portów szeregowych, pamięci itp.

W przypadku urządzeń osadzonych wpisy urządzeń zwykle tworzy się bezpośrednio w głównym systemie plików. Systemy zaawansowane mają skrypt wywoływany MAKEDEVdo tworzenia /devwpisów, ale w systemie osadzonym skrypt często nie jest dołączany do obrazu. Jeśli jakiś sprzęt może być podłączony „na gorąco” (np. Jeśli urządzenie ma port hosta USB), /devpowinien być zarządzany przez udev (nadal możesz mieć minimalny zestaw w głównym systemie plików).

Działania podczas uruchamiania

Poza głównym systemem plików konieczne jest zamontowanie kilku dodatkowych elementów do normalnego działania:

  • procfs włączony /proc(prawie niezbędny)
  • sysfs on /sys(prawie niezbędne)
  • tmpfssystem plików włączony /tmp(aby umożliwić programom tworzenie plików tymczasowych, które będą w pamięci RAM, a nie w głównym systemie plików, który może być we flashu lub tylko do odczytu)
  • tmpfs, devfs lub devtmpfs on /devif dynamic (patrz udev w „ Plikach urządzeń” powyżej)
  • poświęca się, /dev/ptsjeśli chcesz użyć [pseudo-terminali (patrz uwaga na temat ptspowyżej)

Możesz utworzyć /etc/fstabplik i zadzwonić mount -alub uruchomić mountręcznie.

Uruchom demona syslog (jak również klogddzienniki jądra, jeśli syslogdprogram się tym nie zajmuje), jeśli masz jakieś miejsce do zapisywania dzienników.

Następnie urządzenie jest gotowe do uruchomienia usług specyficznych dla aplikacji.

Jak zrobić główny system plików

To długa i różnorodna historia, więc jedyne, co tu zrobię, to kilka wskazówek.

Główny system plików może być przechowywany w pamięci RAM (ładowany z (zwykle skompresowanego) obrazu w pamięci ROM lub flash), lub w systemie plików opartym na dysku (przechowywany w pamięci ROM lub flash) lub ładowany z sieci (często przez TFTP ), jeśli dotyczy . Jeśli główny system plików znajduje się w pamięci RAM, ustaw go jako initramfs - system plików RAM, którego zawartość jest tworzona podczas rozruchu.

Istnieje wiele struktur do składania obrazów głównych dla systemów osadzonych. Istnieje kilka wskazówek w FAQ BusyBox . Buildroot jest popularnym narzędziem, pozwalającym na zbudowanie całego obrazu głównego z konfiguracją podobną do jądra Linuksa i BusyBox. OpenEmbedded to kolejna taka platforma.

Wikipedia ma (niekompletną) listę popularnych osadzonych dystrybucji Linuksa . Przykładem wbudowanego Linuksa, który możesz mieć w pobliżu, jest rodzina systemów operacyjnych OpenWrt dla urządzeń sieciowych (popularna na domowych routerach majsterkowiczów). Jeśli chcesz uczyć się na podstawie doświadczenia, możesz wypróbować Linuksa od podstaw , ale jest on przeznaczony raczej dla komputerów stacjonarnych dla hobbystów niż dla urządzeń osadzonych.

Uwaga na temat jądra Linux vs

Jedynym zachowaniem, które jest upieczone w jądrze Linuksa, jest to, że jest to pierwszy program uruchamiany w czasie rozruchu. (Nie będę wchodził tutaj w subtelności initrd i initramfs .) Ten program, tradycyjnie nazywany init , ma proces ID 1 i ma pewne przywileje (odporność na sygnały KILL ) i obowiązki (zbieranie sierot ). Możesz uruchomić system z jądrem Linuksa i uruchomić cokolwiek chcesz jako pierwszy proces, ale wtedy masz system operacyjny oparty na jądrze Linuksa, a nie to, co zwykle nazywa się „Linux” -  Linux , w zdrowym sensie tego terminu to uniksowy system operacyjny, którego jądrem jest jądro Linux. Na przykład Android to system operacyjny, który nie jest podobny do Uniksa, ale jest oparty na jądrze Linux.


Doskonała odpowiedź. Wspomniałem tylko o rozruchu do Linuksa w tytule b / c, co prawdopodobnie będzie wyszukiwane, więc świetny dodatek o Linuksie w stosunku do jądra Linux, który wymaga szerszej wiedzy.
MDMoore313

@BigHomie Pamiętaj, że Fundacja Wolnego Oprogramowania chce, abyśmy wszyscy nazwali ją GNU / Linux, ponieważ w większości (wszystkich?) „Dystrybucji Linux” oprogramowanie to GNU, mimo że jądro to Linux (stąd GNU / Linux).
BenjiWiebe

Meh, nikt nie ma na to czasu. Zatem moja dystrybucja powinna mieć nazwę Busybox / Linux? Wiem, że wiem, to nie ty jesteś Stallworth, po prostu odpowietrzam;)
MDMoore313

1
@BenjiWiebe Lub GNU / X11 / Apache / Linux / TeX / Perl / Python / FreeCiv . Oprócz RMS wszyscy nazywają to „Linux”.
Gilles „SO- przestań być zły”

@Gilles Cóż, chyba Debiana. :)
CVn

5

Wszystko czego potrzebujesz to jeden statycznie powiązany plik wykonywalny, umieszczony w systemie plików, w izolacji. Nie potrzebujesz żadnych innych plików. Ten plik wykonywalny to proces inicjujący. Może być zajęty. To daje powłokę i wiele innych narzędzi, wszystko samo w sobie. Możesz przejść do w pełni funkcjonalnego systemu, po prostu ręcznie wykonując polecenia w busybox, aby zamontować główny system plików do odczytu i zapisu, utworzyć / dev węzły, wykonać prawdziwy init itp.


Tak, wiedziałem, że nadchodzi busybox. Zobaczmy, czy coś jeszcze się pojawi.
MDMoore313

4

Jeśli nie potrzebujesz żadnych narzędzi powłoki, zrobi to statycznie powiązany mkshplik binarny (np. Przeciwko klibc - 130K w systemie Linux / i386). Potrzebujesz skryptu /linuxrclub /initlub, /sbin/initktóry po prostu wywołuje mksh -l -T!/dev/tty1pętlę:

#!/bin/mksh
while true; do
    /bin/mksh -l -T!/dev/tty1
done

-T!$ttyOpcja jest najnowszym dodatkiem do mkshinformujący go do tarła nową powłokę na danym terminalu i czekać na niego. (Wcześniej było tylko -T-do dæmonise się programm i -T$ttyna tarło na terminalu, ale nie czekać na niego. To nie było tak miło.) -lOpcja po prostu mówi to, aby uruchomić powłokę logowania (który odczytuje /etc/profile, ~/.profilei ~/.mkshrc).

Zakłada się, że twój terminal jest /dev/tty1, zamiennik. (Przy większej magii terminal można automatycznie znaleźć. /dev/consoleNie da ci pełnej kontroli pracy.)

Aby /devto zadziałało, potrzebujesz kilku plików :

  • / dev / console
  • / dev / null
  • / dev / tty
  • / dev / tty1

Uruchamianie z opcją jądra devtmpfs.mount=1eliminuje potrzebę wypełnienia /dev, po prostu niech to będzie pusty katalog (odpowiedni do użycia jako punkt montowania).

Zwykle będziesz chciał mieć jakieś narzędzia (z klibc, busybox, beastiebox, toybox lub toolbox), ale tak naprawdę nie są potrzebne.

Możesz dodać ~/.mkshrcplik, który konfiguruje $ PS1 oraz kilka podstawowych aliasów i funkcji powłoki.

Kiedyś zrobiłem initrd skompresowany (371K nieskompresowany) dla Linux / m68k, używając tylko mksh (i jego przykładowego pliku mkshrc) i tylko klibc-utils. (To było wcześniej, jednak -T! Został dodany do powłoki, więc /dev/tty2zamiast tego uruchomił powłokę logowania i wysłał komunikat do konsoli z informacją, że użytkownik powinien zmienić terminale.) Działa dobrze.

To naprawdę minimalna konfiguracja. Pozostałe odpowiedzi stanowią doskonałą poradę dotyczącą nieco bardziej funkcjonalnych systemów. To jest wyjątkowa sprawa.

Oświadczenie: Jestem programistą mksh.


To świetna odpowiedź, dziękuję za udostępnienie, a także dzięki mksh.
JoshuaRLi

2

Minimalny program init hello world program krok po kroku

wprowadź opis zdjęcia tutaj

Skompiluj cześć świata bez żadnych zależności, które kończą się nieskończoną pętlą. init.S:

.global _start
_start:
    mov $1, %rax
    mov $1, %rdi
    mov $message, %rsi
    mov $message_len, %rdx
    syscall
    jmp .
    message: .ascii "FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n"
    .equ message_len, . - message

Nie możemy użyć sys_exit, inaczej jądro wpadnie w panikę.

Następnie:

mkdir d
as --64 -o init.o init.S
ld -o init d/init.o
cd d
find . | cpio -o -H newc | gzip > ../rootfs.cpio.gz
ROOTFS_PATH="$(pwd)/../rootfs.cpio.gz"

Tworzy to system plików z naszym hello world /init, który jest pierwszym programem dla użytkowników, który uruchomi jądro. Moglibyśmy również dodać więcej plików d/i byłyby one dostępne z /initprogramu podczas działania jądra.

Następnie cdw drzewie jądra Linux, kompilacja jest jak zwykle i uruchom ją w QEMU:

git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
git checkout v4.9
make mrproper
make defconfig
make -j"$(nproc)"
qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd "$ROOTFS_PATH"

I powinieneś zobaczyć linię:

FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR

na ekranie emulatora! Pamiętaj, że nie jest to ostatni wiersz, więc musisz spojrzeć nieco dalej.

Możesz także użyć programów C, jeśli połączysz je statycznie:

#include <stdio.h>
#include <unistd.h>

int main() {
    printf("FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n");
    sleep(0xFFFFFFFF);
    return 0;
}

z:

gcc -static init.c -o init

Możesz działać na prawdziwym sprzęcie z włączonym USB /dev/sdXi:

make isoimage FDINITRD="$ROOTFS_PATH"
sudo dd if=arch/x86/boot/image.iso of=/dev/sdX

Świetne źródło na ten temat: http://landley.net/writing/rootfs-howto.html Wyjaśnia również, jak używać gen_initramfs_list.sh, czyli skryptu z drzewa źródeł jądra Linuksa, który pomaga zautomatyzować proces.

Następny krok: skonfiguruj BusyBox, aby móc współpracować z systemem: https://github.com/cirosantilli/runlinux

Testowane na Ubuntu 16.10, QEMU 2.6.1.

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.