Які мінімальні програми кореневої файлової системи, необхідні для повного завантаження Linux?


17

Це питання про користувацькі простори програм, але вислухайте мене!

Три "програми", так би мовити, потрібні для завантаження функціонального розподілу Linux:

  1. Завантажувач - для вбудованих, як правило, це U-Boot, хоча це не важка вимога.

  2. Ядро - Це досить просто.

  3. Root Filesystem - неможливо завантажуватися до оболонки без неї. Містить файлову систему, до якої завантажується ядро ​​і де initназивається форма.

Моє запитання стосується №3. Якщо хтось хотів створити надзвичайно мінімальні кореневі файли (для цього питання скажімо, не графічний інтерфейс, лише оболонка), які файли / програми потрібні для завантаження в оболонку?


Визначте мінімальний. Ви можете використовувати лише один виконуваний файл, нічого іншого не пояснено, як це пояснено на: superuser.com/a/991733/128124 Просто, що він не може вийти з кожного виходу, інакше панікувати, тому вам потрібна нескінченна петля або тривалий сон. Аналогічне запитання: unix.stackexchange.com/questions/17122/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Відповіді:


32

Це повністю залежить від того, які послуги ви хочете мати на своєму пристрої.

Програми

Ви можете зробити завантаження Linux безпосередньо в оболонку . Він не дуже корисний у виробництві - хто просто хотів би, щоб там сидів оболонка - але він корисний як механізм втручання, коли у вас є інтерактивний завантажувач: перейдіть init=/bin/shдо командного рядка ядра. Усі системи Linux (і всі системи Unix) мають оболонку в стилі Bourne / POSIX /bin/sh.

Вам знадобиться набір утиліт оболонок . BusyBox - дуже поширений вибір; вона містить оболонку і загальні утиліти для файлу і обробки тексту ( cp, grep, ...), мережеві настройки ( ping, ifconfig, ...), маніпуляції з процесом ( ps, nice, ...), а також різні інші інструменти системи ( fdisk, mount, syslogd...). BusyBox надзвичайно настроюється: ви можете вибрати інструменти, які ви хочете, та навіть окремі функції під час компіляції, щоб отримати компроміс потрібного розміру та функціональності для вашої програми. Крім sh, голий мінімум , який ви не можете зробити нічого не їсти mount, umountі halt, але було б нетиповою не мають також cat, cp, mv, rm,mkdir, rmdir, ps, syncІ ще кілька. BusyBox встановлюється у вигляді єдиного двійкового виклику busyboxз символічним посиланням для кожної утиліти.

Перший процес у звичайній системі Unix називається init. Його завдання - запускати інші послуги. BusyBox містить систему init. На додаток до initбінарних файлів (зазвичай розташованих у /sbin) вам знадобляться файли конфігурації (як правило, це називається /etc/inittab- деякі сучасні замінники init скасовують цей файл, але ви не знайдете їх у невеликій вбудованій системі), які вказують, які служби запустити і коли. Для BusyBox /etc/inittabнеобов’язково; якщо він відсутній, ви отримуєте кореневу оболонку на консолі і сценарій /etc/init.d/rcS(місце за замовчуванням) виконується під час завантаження.

Це все, що вам потрібно, крім звичайно програм, які змушують ваш пристрій робити щось корисне. Наприклад, на моєму домашньому маршрутизаторі, що працює у варіанті OpenWrt , єдиними програмами є BusyBox nvram(для читання та зміни налаштувань у NVRAM) та мережеві утиліти.

Якщо всі ваші виконувані файли статично не пов'язані, вам знадобиться динамічний завантажувач ( ld.soякий може викликатися різними іменами залежно від вибору libc та архітектури процесора) та всі динамічні бібліотеки ( /lib/lib*.soможливо, деякі з них у /usr/lib), необхідні ці виконувані файли.

Структура каталогів

Filesystem Hierarchy Standard описує загальну структуру каталогів системи Linux. Він орієнтований на встановлення настільних та серверних систем: багато чого можна опустити у вбудованій системі. Ось типовий мінімум.

  • /bin: виконувані програми (деякі можуть бути /usr/binзамість них).
  • /dev: вузли пристрою (див. нижче)
  • /etc: файли конфігурації
  • /lib: спільні бібліотеки, включаючи динамічний завантажувач (якщо всі виконувані файли статично не пов'язані)
  • /proc: точка монтування файлової системи proc
  • /sbin: виконувані програми. Відмінність /binполягає в тому, що /sbinце стосується програм, які корисні лише системному адміністратору, але це відмінність не має сенсу на вбудованих пристроях. Ви можете зробити /sbinсимвольне посилання на /bin.
  • /mnt: зручно мати в кореневих файлових системах лише для читання як точку кріплення подряпин під час обслуговування
  • /sys: точка монтування файлової системи sysfs
  • /tmp: місце для тимчасових файлів (найчастіше tmpfsкріплення)
  • /usr: Містить підкаталоги bin, libі sbin. /usrіснує для додаткових файлів, які відсутні в кореневій файловій системі. Якщо у вас цього немає, ви можете зробити /usrсимвольне посилання на кореневий каталог.

Файли пристроїв

Ось кілька типових записів мінімально /dev:

  • console
  • full (писати до нього завжди повідомляє "на пристрої не залишилося місця")
  • log(сокет, який програми використовують для надсилання записів у журнал), якщо у вас syslogdдемон (такий як BusyBox) читає з нього
  • null (діє як файл, який завжди порожній)
  • ptmxі ptsкаталог , якщо ви хочете використовувати псевдо-термінали (тобто будь-який термінал, окрім консолі) - наприклад, якщо пристрій підключений до мережі та ви хочете передати телнет або ssh в
  • random (повертає випадкові байти, ризикує блокувати)
  • tty (завжди позначає термінал програми)
  • urandom (повертає випадкові байти, ніколи не блокується, але може бути невипадковим на щойно завантаженому пристрої)
  • zero (містить нескінченну послідовність нульових байтів)

Крім цього вам знадобляться записи для вашого обладнання (крім мережевих інтерфейсів, вони не отримують записи /dev): послідовних портів, сховища тощо.

Для вбудованих пристроїв зазвичай можна створювати записи пристрою безпосередньо в кореневій файловій системі. Системи високого класу мають сценарій, який викликається MAKEDEVдля створення /devзаписів, але у вбудованій системі сценарій часто не вбудовується в зображення. Якщо деяке обладнання може бути підключено гарячою підключенням (наприклад, якщо у пристрою є хост-порт USB), то ним /devслід керувати udev (у вас все одно можливий мінімальний набір у кореневій файловій системі).

Дії під час завантаження

Крім кореневої файлової системи, для нормальної роботи потрібно встановити ще кілька:

  • profs on /proc(досить незамінний)
  • sysfs on /sys(майже незамінний)
  • tmpfsувімкнено файлову систему /tmp(щоб дозволити програмам створювати тимчасові файли, які будуть знаходитися в оперативній пам'яті, а не в кореневій файловій системі, яка може бути в режимі flash або лише для читання)
  • tmpfs, devfs або devtmpfs увімкнено, /devякщо вони динамічні (див. udev у " Файлах пристроїв" вище)
  • devpts on, /dev/ptsякщо ви хочете використовувати [псевдотермінали (див. зауваження про ptsвище)

Ви можете зробити /etc/fstabфайл і зателефонувати mount -aабо запустити mountвручну.

Запустіть демон- syslog (як і klogdдля журналів ядра, якщо syslogdпрограма не піклується про нього), якщо у вас є куди писати журнали.

Після цього пристрій готовий запустити послуги, що стосуються додатків.

Як зробити кореневу файлову систему

Це довга і різноманітна історія, тому все, що я тут роблю, - це дати кілька покажчиків.

Коренева файлова система може зберігатися в оперативній пам’яті (завантажується з (зазвичай стисненого) зображення в ПЗУ або спалаху), або в файловій системі на основі диска (зберігається в ПЗУ або флеш), або завантажується з мережі (часто через TFTP ), якщо це застосовується . Якщо коренева файлова система знаходиться в оперативній пам'яті, зробіть її initramfs - файловою системою ОЗУ, вміст якої створюється під час завантаження.

Існує багато фреймворків для складання кореневих зображень для вбудованих систем. У FAQ щодо BusyBox є кілька покажчиків . Buildroot - популярний, що дозволяє будувати ціле зображення кореня із налаштуваннями, подібними до ядра Linux та BusyBox. OpenEmbedded - це ще одна така структура.

У Вікіпедії є (неповний) список популярних вбудованих дистрибутивів Linux . Прикладом вбудованого Linux, який ви можете мати поруч, є сімейство операційних систем OpenWrt для мережевих приладів (популярне на домашніх маршрутизаторах tinkerers). Якщо ви хочете дізнатися на досвіді, ви можете спробувати Linux від Scratch , але він орієнтований на настільні системи для любителів, а не на вбудовані пристрої.

Примітка про ядро ​​Linux проти Linux

Єдине поведінка, яке вкладається в ядро ​​Linux, - це те, що перша програма, яка запускається під час завантаження. (Тут я не вникатиму в тонкощі initrd та initramfs .) Ця програма, яку традиційно називають init , має ID 1 процесу та має певні привілеї (несприйнятливість до сигналів KILL ) та обов'язки (пожинання сиріт ). Ви можете запустити систему з ядром Linux і почати все, що ви хочете, як перший процес, але тоді у вас є операційна система, заснована на ядрі Linux, а не те, що зазвичай називається "Linux" -  Linux , у загальному розумінні терміна - це операційна система, схожа на Unix , ядром якої є ядро Linux. Наприклад, Android - це операційна система, яка не схожа на Unix, але заснована на ядрі Linux.


Відмінна відповідь. Я лише згадав про завантаження в Linux у заголовку b / c, саме це, ймовірно, буде шукати, настільки чудове доповнення про Linux проти Linux Kernel, що потребує більш широких знань.
MDMoore313

@BigHomie Пам'ятайте, що Фонд вільного програмного забезпечення хоче, щоб ми всі називали його GNU / Linux, оскільки у більшості (всіх?) Програмних засобів "Linux distros" програмне забезпечення є GNU, навіть незважаючи на те, що ядро ​​є Linux (отже, GNU / Linux).
BenjiWiebe

Мех, на це ніхто не має часу. Тоді мій дистрибутив повинен називатися Busybox / Linux ?? Я знаю, що знаю, це не ти його Сталлворт, просто вентиляція;)
MDMoore313

1
@BenjiWiebe Або GNU / X11 / Apache / Linux / TeX / Perl / Python / FreeCiv . Крім RMS, всі називають це «Linux».
Жил "ТАК - перестань бути злим"

@Gilles Ну, крім Debian, я думаю. :)
CVn

5

Все, що вам потрібно, - це один статично пов'язаний виконуваний файл, розміщений у файловій системі, ізольовано. Вам не потрібні інші файли. Цей виконуваний файл є процесом init. Це може бути зайнята скринька. Це дає вам оболонку та безліч інших утиліт, все саме по собі. Ви можете перейти до повністю функціонуючої системи, просто виконуючи команди вручну в зайнятому ящику для монтажу кореневої файлової системи для читання-запису, створення / dev вузлів, exec real init тощо.


Так, я знав, що зайнята скринька приходить. Давайте подивимося, чи з’явиться щось інше.
MDMoore313

4

Якщо вам не потрібні будь-які утиліти оболонки, зробиться статично пов'язаний mkshбінарний файл (наприклад, проти klibc - 130K в Linux / i386). Вам потрібен /linuxrcабо /initабо /sbin/initсценарій, який просто дзвонить mksh -l -T!/dev/tty1у циклі:

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

-T!$ttyВаріантом є недавнє доповнення до , mkshщо говорить йому , щоб породити нову оболонку на даний термінал і чекати його. (До цього був тільки -T-в dæmonise програмка і -T$ttyна ікру на термінал , але не чекати. Це було не так красиво) . В -lопції просто говорить йому , щоб запустити оболонку входу в систему (яка читає /etc/profile, ~/.profileа ~/.mkshrc).

Це передбачає, що ваш термінал є /dev/tty1, підміняти. (З більш магією термінал може бути автоматично знайдений. /dev/consoleНе дасть вам повного контролю за роботою.)

Для цього вам потрібно кілька файлів /dev:

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

Завантаження з параметром ядра devtmpfs.mount=1виключає необхідність заповнення /dev, просто нехай це буде порожній каталог (підходить для використання в якості точки монтажу).

Зазвичай ви хочете мати деякі утиліти (від klibc, busbox, beastiebox, іграшка або панель інструментів), але вони насправді не потрібні.

Ви можете додати ~/.mkshrcфайл, який встановлює $ PS1 та деякі основні псевдоніми та функції оболонки.

Одного разу я зробив initrd для стискання 171К (нестиснений 371К) для Linux / m68k, використовуючи лише mksh (і його зразок файлу mkshrc) та klibc-утиліти. (Це було раніше, ніж -T! Було додано до оболонки, однак, тому він породив оболонку входу /dev/tty2натомість, і повторив повідомлення на консолі, що сповіщає користувача про перемикання терміналів.) Це працює чудово.

Це дійсно мінімум налаштувань. Інші відповіді дають чудові поради щодо дещо кращих систем. Це справжня річ в особливих випадках.

Відмова: Я розробник mksh.


Це чудова відповідь, дякую за спільний доступ, а також дякую mksh.
ДжошуаРЛІ

2

Мінімальна покрокова програма програми init hello

enter image description here

Складіть привіт світ без будь-яких залежностей, який закінчується нескінченним циклом. 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

Ми не можемо використовувати sys_exit, інакше ядра панікує.

Потім:

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"

Це створює файлову систему з нашим привітним світом at /init, який є першою програмою для користувача, яка буде запускати ядро. Ми також могли б додати більше файлів, d/і вони будуть доступні через /initпрограму під час запуску ядра.

Потім cdу дерево ядра Linux, збирайте як завжди і запускайте його в 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"

І вам слід побачити рядок:

FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR

на екрані емулятора! Зауважте, що це не останній рядок, тому вам доведеться дивитися трохи далі.

Ви також можете використовувати програми C, якщо з'єднати їх статично:

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

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

з:

gcc -static init.c -o init

Ви можете працювати на справжньому обладнанні, використовуючи USB /dev/sdXта:

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

Чудове джерело на цю тему: http://landley.net/writing/rootfs-howto.html Також роз'яснюється, як використовувати gen_initramfs_list.shсценарій із дерева вихідного ядра Linux для автоматизації процесу.

Наступний крок: налаштування BusyBox, щоб ви могли взаємодіяти з системою: https://github.com/cirosantilli/runlinux

Тестовано на Ubuntu 16.10, QEMU 2.6.1.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.