Differences

This shows you the differences between two versions of the page.

Link to this comparison view

si:laboratoare:08 [2023/12/03 20:28]
florin.stancu
— (current)
Line 1: Line 1:
-====== Laboratorul 08. RootFS Bootstrapping ====== 
- 
-===== Crearea unei distribuții Linux ===== 
- 
-Până acum am folosit Root Filesystem de-a gata pre-instalat. 
- 
-La acest laborator, dorim să învățăm procesul de generare a unui sistem de bază și modalitățile de personalizare a acestuia, proces numit **rootfs bootstrapping**. 
- 
-Avem 2 variante: 
-  * plecarea de la o distribuție existentă și alegerea pachetelor pe care să le includem + configurații specifice; 
-  * compilarea (manuală sau automată) a tuturor componentelor unui astfel de sistem; 
- 
-Prima soluție, deși mult mai facilă (atât rapidă, cât și ușor de înțeles), nu ne permite o optimizare a spațiului utilizat (sisteme bazate pe Debian ocupă de ordinul ''​~1GB''​) și nici fine-tuningul ulterior pentru îmbunătățirea performanțelor în cazul rulării pe anumite dispozitive (e.g., ARMv8 cu extensii NEON pentru SIMD). 
- 
-Pe de altă parte, dacă am dori să facem asta de la zero, ar trebui să plecăm de la un toolchain (pe care, de cele mai multe ori, trebuie să-l compilăm tot noi), pe care îl vom folosi să compilăm din cod sursă toate componentele necesare într-un sistem Linux: biblioteci standard (LibC), sistem de init (SystemV / SystemD / OpenRC etc.), suita de programe de bază Unix (e.g., ''​mount'',​ ''​cat'',​ ''​ls'',​ ''​cp'',​ ''​sh'',​ ''​awk''​ și multe altele!), device manager (''​udev''​) precum și multe alte servicii (e.g., de networking) și aplicații necesare scopului nostru final (e.g., Python, X11 + QT Toolkit pentru interfețe grafice etc.). 
- 
-Din fericire, există suite software ([[https://​www.yoctoproject.org/​|Yocto Linux]], [[https://​buildroot.org/​|Buildroot]]) care pot automatiza repetabil acest proces. Însă un dezavantaj tot rămâne: timpul de compilare este de ordinul orelor, iar spațiul pe disk necesar între ''​20GB -- 50GB''​. 
- 
- 
-===== Exerciții ===== 
- 
-Pentru acest laborator, vom încerca ambele abordări! 
- 
-==== 1. Crearea de distribuții bazate pe Debian (debootstrap) ==== 
- 
-Pentru a genera distribuții personalizate bazate pe Debian (și derivate, e.g., Ubuntu), se poate folosi utilitarul ''​debootstrap''​. 
- 
-Acesta descarcă automat din repository-uri pachetele ''​.dpkg'',​ pe care le instalează într-un prefix (director) precizat de utilizator, e.g.: 
-<code shell> 
-$ sudo debootstrap --arch="​arm64"​ --include="​vim bash curl" \ 
-        --variant=minbase "​bookworm"​ "/​root/​mydebian/"​ "​http://​ftp.de.debian.org/​debian"​ 
-</​code>​ 
- 
-<note tip> 
-Aproape toate distribuțiile de Linux au câte un utilitar (de multe ori, chiar package managerul distribuției) care permite bootstrappingul RootFS-urilor din pachete (tot așa sunt generate și imaginile ISO live!). 
-Spre exemplu, Arch Linux are ''​pacstrap'',​ Alpine Linux are ''​apk.static''​ and so on... 
-</​note>​ 
- 
-De menționat ar fi că instalarea unui pachet are loc în 2 etape: 
-  * decompresia arhivelor și extragerea fișierelor în directorul destinație;​ 
-  * rularea unor scripturi post-install pentru crearea configurațiilor implicite / upgrade fișiere / integrarea cu alte aplicații / instalarea serviciilor etc.; 
- 
-Acest aspect devine important când încercăm să generăm un rootfs pentru o arhitectură străină celei gazdă (cross-bootstrapping)! 
-Pentru a realiza acest lucru, va trebui să distingem cele două etape: decompresia va putea avea loc direct pe host (avem utilitarele necesare instalate cu scriptul de bootstrapping),​ pe când etapa de execuție a programelor va trebui să fie virtualizată cumva (chroot + ''​qemu-user-static''​ FTW). 
- 
-Astfel, pentru a realiza ''​debootstrap''​ de pe o arhitectură Intel/AMD ''​x86_64''​ pentru o țintă AArch64 (ARM 64-bit), vom avea de realizat următoarele:​ 
-<code shell> 
-$ sudo debootstrap --foreign --arch="​arm64"​ ... /​root/​mydebian ... # restul de argumente normale 
-# apoi copiem emulatorul în noua rădăcină (va fi rulat de binfmt_misc ca în Lab 04) 
-$ sudo cp -af "​$(which qemu-aarch64-static)"​ /​root/​mydebian/​usr/​bin/​ 
-# Acum va trebui să rulăm stagiul 2 al debootstrap,​ însă într-un container / chroot! 
-# Folosim systemd-nspawn pentru a rula binarul de second-stage instalat pe rootfs de la primul: 
-$ sudo systemd-nspawn -as-pid2 --resolv-conf=copy-host -D /​root/​mydebian \ 
-    /​debootstrap/​debootstrap --second-stage --verbose 
-</​code>​ 
- 
-Tehnica cu systemd-nspawn + qemu-user-static (și binfmt_misc) este utilă pentru a intra într-un chroot pe rootfs-ul nostru pentru a-l personaliza (putem chiar și instala programe noi sau configura servicii etc.). Însă va trebui configurat gestionarul de pachete, ''​apt'':​ de adăugat mirror-uri la repo-urile de bază în ''/​etc/​apt/​sources.list''​ -- [[https://​wiki.debian.org/​SourcesList#​Example_sources.list|găsiți exemplu aici]]. 
- 
-**Atenție:​** momentan, rootfs-ul NU ARE parolă la contul ''​root''​ (și nu are nici un alt cont) și nu vă veți putea autentifica din niciun //tty//! 
-Se recomandă accesarea unui chroot (rulați ''/​usr/​bin/​bash''​ ca ultim argument al lui ''​systemd-nspawn''​) și setarea uneia prin ''​passwd''​. 
- 
-O dată generat rootfs-ul, acesta trebuie copiat (atenție să nu se piardă permisiunile și atributele unor fișiere speciale -- mai ales symlink-urile) pe o partiție și bootat! Se recomandă arhivarea acestuia folosind utilitarul ''​tar''​ (acesta salvând automat metadatele necesare în arhivă):<​code shell> 
-$ tar czf mydebian.tar.gz -C /​root/​mydebian 
-</​code>​ 
- 
-În final, dorim să vedem cât ocupă rootfs-ul nostru: 
-<code shell> 
-$ du -hs /​root/​mydebian 
-</​code>​ 
- 
-<note tip> 
-Vom trece să instalăm + rulăm sistemul pe un Raspberry PI 4 fizic imediat ce pornim compilarea unui sistem Buildroot ;) 
-</​note>​ 
- 
-==== 2. Compilarea programelor de bază (buildroot) ==== 
- 
-Mai departe, descriem procesul de utilizare al unui utilitar destul de popular (cel mai important fiind ușurința de învățare față de Yocto Linux). 
- 
-**TODO** 
- 
-==== 3. Instalarea rootfs-ului în imaginea RPI 4 ==== 
- 
-**0.** Descărcați [[https://​github.com/​cs-pub-ro/​SI-rpi-debian-scripts/​releases|de aici imaginea rpi-empty.img.tar.xz]]. 
- 
-**1.** Trebuie să montăm imaginea și să copiem noul RootFs pe cea de a doua partiție (este creată deja!): 
- 
-  * Dezarhivați fișierul imaginii ''​rpi-empty'';​ ar trebui să obțineți o imagine de ''​2GB'';​ 
-  * Verificați că există ambele partiții: ''​parted rpi-empty.img print'';​ 
-  * Conectați imaginea la un dispozitiv de tip bloc folosind ''​losetup /dev/loop0 rpi-empty.img''​ (verificați cu ''​losetup -L''​ ce aveți conectat dacă întâmpinați probleme); 
-  * Formatați sistemul de fișiere a celei de-a doua partiții în ext4: ''​mkfs.ext4 -L RPI_ROOTFS /​dev/​loop0p2''; ​ 
-  * Montați noua partiție goală ''​ext4''​ (puteți folosi ''/​mnt''​ ca mountpoint) și copiați conținutul arhivei rootfs generate anterior (ori cea de Debian, ori cea obținută prin Buildroot): <code shell> 
-tar xf <​ARCHIVE_FILE>​ -C <​DEST_MOUNTPOINT>​ 
-# inspectați calea dezarhivată:​ 
-ls -l <​DEST_MOUNTPOINT>​ 
-</​code>​ 
-  * Demontați partiția ext4 și deconectați dispozitivul ''​loop''​ folosite! 
- 
-**2.** Porniți Raspberry PI-ul în u-boot, apoi intrați în modul ''​ums mmc X''​ (vedeți [[:​si:​laboratoare/​05|laboratorul 5]]); folosiți ori ''​dd'',​ ori un utilitar de Raw Disk Imager pentru Windows (recomandat:​ Raspberry PI Imager) ca la laboratoarele anterioare pentru a scrie noua imagine pe RPI. 
- 
-<note important>​ 
-  * **Atenție**:​ Va trebui, mai întâi, să aduceți imaginea pe Windows (folosiți ''​scp''​ cu ''​username@<​ip_sursa>:/​cale/​catre/​fisier.img''​ ca prim argument, iar, ca destinație,​ o cale de pe PC-ul fizic, e.g., ''​C:​\Users\..etc''​)! 
-  * **Notă pentru VirtualBox**:​ va trebui să folosiți argumentul ''​-P 2023''​ și ''​student@localhost:<​cale>''​ ca sursă. 
-  * **Notă pentru cei cu gazda pe Linux**: dacă utilizați ''​dd'',​ va trebui să rulați comanda ''​sync''​ și să așteptați să se termine! Asta e important deoarece kernelul modern cache-uiește în memoria RAM și scrierea se termină, aproape instant (însă rămâne să se copieze pe SD în background, această operațiune fiind mult mai lentă). 
-</​note>​ 
- 
-3. Reporniți Raspberry PI-ul. Lăsați-l să booteze normal, ar trebui să pornească kernel-ul implicit cu rootfs-ul vostru! 
- 
-  * Inspectați-l! Cât ocupă pe disk (''​df''​)?​ 
-  * Dacă vă printează mesajul cu ''​waiting for device /​dev/​mmcblk0p2''​ și nu se termină procesul, verificați dacă partiția a doua există din u-boot (''​part list mmc 0''​). 
- 
-==== 4. [BONUS] Rulați imaginea voastră în QEmu (system) ==== 
- 
-Observăm că procesul de testare a unei imagini embedded consumă ceva timp (mai ales la scrierea pe cardul SD). 
-Dorim să optimizăm! 
- 
-Rulați imaginea obținută anterior (va trebui să exrageți kernel-ul din imagine!) prin ''​qemu-system-aarch64''​. 
-Re-vedeți instrucțiunile din [[:​si:​laboratoare/​04|laboratorul 4]]. 
- 
-===== Resurse ===== 
- 
-  * [[https://​github.com/​cs-pub-ro/​SI-rpi-debian-scripts|Cod sursă scripturi compilare bootloader / kernel / generare rootfs]] 
-  * [[https://​buildroot.org/​downloads/​manual/​manual.html#​_getting_started|Buildroot Manual - Getting started]] 
- 
  
si/laboratoare/08.1701628117.txt.gz · Last modified: 2023/12/03 20:28 by florin.stancu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0