Construiți-vă propriul kernel Linux

Uneori poate fi necesar să-ți construiești propriul tău Nucleul Linux. Motivele pentru aceasta pot fi următoarele:

  • ai nevoie de un nucleu curat, fara patch-uri de distributie;
  • vrei să-ți aplici propriile plasturi (dintre care există o mulțime);
  • doriți să asamblați un nucleu pentru a se potrivi configurației dvs. hardware, să aruncați lucrurile inutile din el și/sau să-l adaptați pentru sarcini specifice;
  • doriți să includeți un driver experimental sau un sistem de fișiere în nucleu care nu este inclus în "vanilie" nucleu (de exemplu ZFS sau Ridicator 4);
Nu este nimic complicat în asamblarea nucleului. Este important doar să înțelegeți de ce se face acest lucru și, de asemenea, să nu atingeți acei parametri pe care nu îi înțelegeți. În această notă voi descrie două exemple de construire a unui nucleu în Bazat pe Debian distribuţiile. În primul exemplu, voi arăta cât de ușor este să asamblați un miez pur, așa-numitul „vanilie” (cum este eliberat de Linus Torvalds ), iar în al doilea - cum să aplicați propriile patch-uri și să optimizați nucleul. Voi scrie imediat două avertismente:
  • va trebui să reconstruiți nucleul de fiecare dată când este actualizat (descărcați „patch-ul de actualizare”, aplicați-l și asamblați nucleul);
  • nucleul reconstruit poate să nu funcționeze dacă sistemul dvs. folosește niște hack-uri pentru a asigura funcționalitatea acestui sau aceluia echipament;
  • Dacă nucleul este configurat incorect, mai ales în cazul aplicării analfabete sau necugetate a patch-urilor, puteți fie să ajungeți la un sistem care este teribil de lent, fie să îl pierdeți cu totul.
EFECTUAȚI TOATE ACȚIUNILE PE PROPRIU RISC!

Asamblare simplă a nucleului fără patch-uri.

Codul sursă al nucleului Linux este disponibil la kernel.org. Există, de asemenea "actualizare patch-uri". De ce avem nevoie? Descărcați de pe site tarball(arhivă) cu cea mai recentă versiune stabilă a nucleului (la momentul scrierii, aceasta este versiunea 4.3 ). Descărcați în orice mod convenabil. În continuare avem nevoie de instrumente pentru asamblare:

sudo apt install build-essential gcc kernel-package patch
sudo apt-get build-dep linux

După ce totul este instalat instrumentele necesare, despachetați arhiva cu codul kernelului în orice director convenabil. Lăsați-l să fie /home/user/KERNEL, Unde "utilizator"- numele de utilizator al sistemului. Apoi, deschideți un terminal și mergeți acolo:

cd /home/user/KERNEL

Tot ce rămâne este să asamblați nucleul:

fakeroot make-kpkg -j 3 --initrd --append-to-version=-custom kernel_image kernel_headers #-j 3

Numărul 3 după j- acesta este numărul de nuclee ale procesorului tău + 1. Adică pentru un procesor dual-core este 3, pentru un procesor cu 4 nuclee este 5 și așa mai departe.
-personalizat- aici puteți specifica un nume convenabil pentru nucleu pentru a face mai ușor să-l distingeți de cel de distribuție.
kernel_imageȘi kernel_headers- acesta este nucleul însuși și, respectiv, fișierele sale de antet. Anteturi necesare pentru asamblarea driverelor și modulelor kernelului, precum și pentru alte scopuri. După rularea acestei comenzi, vor începe să apară câteva întrebări de configurare a nucleului. Deoarece lăsăm totul ca implicit, trebuie doar să apăsați Enter până când începe construcția. În funcție de puterea computerului, asamblarea poate dura de la 15-20 de minute la câteva ore. După asamblare, în director /acasă/utilizator vor apărea două pachet deb: miez și anteturi. Instalați-le cu comanda:

sudo dpkg -i linux-image-4.3*deb linux-headers-4.3*deb
sudo update-grub

Și reporniți. În meniul GRUB puteți selecta acum un alt nucleu pentru a porni sistemul.

Construirea nucleului folosind patch-uri și configurații suplimentare.

De data aceasta vom construi un nucleu optimizat pentru lucrul cu sunet și video, precum și pentru o mai mare capacitate de răspuns a sistemului. Pentru a face acest lucru, vom aplica două patch-uri: așa-numitul patch-uri în timp real ( PREEMPT RT) și un patch pentru compilator GCC pentru a adăuga opțiuni suplimentare pentru optimizarea procesorului. În primul rând, ce este un plasture? Patch-ul este fisier text, care este creat de program dif, care conțin modificări de cod în anumite părți, care, la aplicarea patch-ului, sunt introduse în locurile potrivite. Deoarece Patch RT iese cu o mare întârziere, cea mai recentă versiune este pentru nucleul 4.1. Cu toate acestea, acest lucru nu este atât de important. Folosind aceeași schemă, descărcați kernel-ul 4.1 de pe kernel.org și despachetați-l într-un director /home/user/KERNEL-CUSTOM. Acum descărcați patch-urile. PREEMPT_RT și corecția GCC. Din arhivele descărcate avem nevoie de fișiere cu extensia .patch, care trebuie plasate în directorul cu codul sursă al kernelului. Adică în /home/user/KERNEL-CUSTOM. Înainte de a aplica plasturi, trebuie să vă asigurați că nu există erori. Deschide terminalul:

cd /home/user/KERNEL-CUSTOM
patch -p1 -i patch-4.1.13-rt15.patch --dry-run


Opțiune --funcție uscată vă permite să simulați aplicarea unui patch, fără a face modificări fișierelor. Dacă nu sunt găsite erori (vezi captura de ecran) - acceptați patch-ul fără opțiunea --funcție uscată. Efectuați acțiuni similare cu al doilea plasture. Nu aplicați mai mult de un plasture o dată! Acum trebuie să ne configuram nucleul. Avem următoarele opțiuni din care să alegem:

face config- întrebările despre configurarea unuia sau altuia subsistem kernel vor fi afișate în terminal pe rând. Un proces extrem de lung și plictisitor. Sa uitam de asta :)
face oldconfig- se va folosi configurația nucleului care rulează în prezent. Deoarece le asamblam pe ale noastre de la zero, această metodă este, de asemenea, inutilă.
face defconfig- similar cu cel precedent, doar valorile vor fi implicite. Modul în care dezvoltatorii nucleului l-au stabilit. Similar cu prima metodă de asamblare.
face menuconfig- interfață pseudo-grafică bazată pe bibliotecă Nblesteme. Pe ecran va fi afișată o interfață cu un meniu ierarhic convenabil. Controale folosind direcția, spațiul și Tastele TAB. Recomandat dacă construiți nucleul pe un sistem care nu are înveliș grafic.
face gconfig GTK, recomandat în GNOME, Mate, Xfce, Cinnamon, Unity și altele care folosesc GTK.
face xconfig- Bazat pe GUI Qt. Recomandat în KDE. Deoarece sistemul meu folosește KDE, voi folosi această metodă. În plus, mai există câteva metode, dar aplicarea lor nu este diferită. Așa că, după aplicarea patch-urilor, lansăm face xconfigși iată ce apare în fața noastră:


În primul rând, opriți dynticks. Pentru a face asta mergem la Subsistemul cronometreși alegeți Timpurile periodice ale cronometrului


Acum partea cea mai bună. Să mergem la Tipul și caracteristicile procesoarelor, caut un articol Familia de procesoareși indicați seria procesorului dvs. De exemplu, dacă ai Intel core i5-4xxx, indicați Hasswell(procesor de generația a 4-a). Dacă nu sunteți sigur exact, puteți selecta articolul Optimizări native detectate automat de GCC. În acest caz, în timpul asamblarii, compilatorul însuși va determina ce suportă procesorul dvs. și va include toate caracteristicile sale.


Mergeți mai jos și activați parametrul Nucleu complet preemptibil (RT). Modul greu în timp real.


Derulați în jos și la punctul respectiv Frecvența cronometrului setați frecvența de întrerupere a sistemului la 1000 Hz


Oprim complet orice economie de energie. Este important! În stânga căutăm un articol Opțiuni de gestionare a energiei și ACPIși debifați ACPI. Dezactivați și economisirea energiei procesorului

Asta e tot. Dacă doriți (și studiați cu atenție documentația), puteți intra modificări suplimentare la configurație (dezactivare șoferi suplimentari, utilizați subsisteme suplimentare și așa mai departe). Acum salvăm configurația prin Fișier - Salvare, închideți configuratorul și asamblați nucleul:

fakeroot make-kpkg -j 3 --initrd --append-to-version=-rt-custom kernel_image kernel_headers #-j 3
sudo update-grub

Pe computerul meu cu procesor Intel Core i3-550 (3,2 GHz), creșterea performanței a fost destul de vizibilă. Dar cel mai important lucru este atunci când lucrezi LMMSȘi Kdenlive, bâlbâială periodică, desincronizare a pieselor audio și video, precum și înghețarea când incarcatura grea la hard disk. Concluzie - funcționează! În cele din urmă, voi descrie două nuclee modificate, care sunt foarte populare în cercurile Linux:

PF-kernel- cel mai popular set de plasturi de la ucraineanul Alexander Natalenko (aka post-factum). Acesta este un set de patch-uri care nu sunt incluse în nucleul principal, dar oferă o capacitate de răspuns sporită a sistemului, oferă un subsistem alternativ de hibernare care este mai rapid decât cel principal și, de asemenea, reduc utilizarea memoriei folosind o tehnică de pooling. pagini identice. Setul include:

  • Programator de proces BFS de Con Kolivas cu remedieri suplimentare de la Alfred Chen;
  • BFQ I/O scheduler de Paolo Valente, Arianna Avanzini și Mauro Marinoni;
  • subsistemul de hibernare TuxOnIce de la Nigel Cunningham;
  • implementarea tehnicii de îmbinare a paginilor identice în memoria UKSM de la Nai Xia;
  • patch de la Graysky, extinzând lista de procesoare pentru optimizarea nucleului de către compilator (cel pe care l-am aplicat mai sus)
Repozitoriu kernel modificat. Site-ul oficial .

Zen-kernel- al doilea cel mai popular set, dar primul ca număr de patch-uri. Kernel-ul Zen folosește o combinație de mai multe proiecte, actualizează codul printr-un depozit git și, de asemenea, are mai multe lucruri specifice Zen care urmăresc să satisfacă majoritatea nevoilor utilizatorilor într-un singur nucleu. Câteva caracteristici ale patch-ului: drm-next, testare fără fir, alegere de programatoare CPU (CFS/BFS), planificator BFQ I/O, aufs, unionfs, reiser4, tuxonice, PHC și multe alte lucruri care sunt grozave pentru optimizarea sistemelor desktop sau laptopuri. Toate acestea sunt disponibile sub forma unui patch la miezul de vanilie. Site-ul oficial . Depozitul GIT. Pachete pentru Debian/Ubuntu.

Probabil asta e tot pentru ziua de azi. Mai multe informații găsiți în linkurile către articol. Tot ce este descris în articol a fost testat de mine pe multe configurații.

Într-o familie mare de sisteme de operare bazate pe GNU/Linux. Cu siguranță ați auzit că aceste coduri sunt deschise, distribuite gratuit și gratuite. Se spune, ia-l pe cine vrei, dar respectă doar termenii licenței GPL, ceea ce nu este deloc dificil. Cu toate acestea, puțini oameni explică suficient de clar care este esența acestui fenomen, care este sensul acestuia. Prin urmare, vom încerca o astfel de explicație.

Esența pe scurt

Totul a început în 1991, când studentul finlandez Linus Torvalds a făcut publice codurile kernelului noului sistem de operare Linux. De ce în aer liber? Pentru că a susținut. Dar probabil că știți deja acest lucru (sau aflați ușor). Vom acorda atenție punctelor care necesită o clasificare clară.

Linux

Linux nu este sistem de operare, ci doar miezul. Un set de soluții software necesare pentru pornirea unui computer și funcționarea componentelor acestuia („hardware”), baza pentru funcționarea altor programe.

GNU

GNU este un set de aplicații simple care au existat chiar înainte de apariția nucleului de mai sus. Aceste programe permit unei persoane să efectueze cel puțin o anumită interacțiune cu computerul și nu doar să se uite la ecran. Codul sursă este și el deschis, desigur.

GNU/Linux este un sistem de operare, nu doar un nucleu. În loc de GNU, poate exista altceva, de exemplu Dalvik în Android.

Șoferii

Tehnologia se dezvoltă, numărul hardware-ului computerelor este în creștere, echipamentele evoluează. Și fiecare produs are nevoie de un driver pentru a funcționa. Deci, unele drivere sunt înșurubate direct la miez. Dacă sunt gratuite (software liber), precum GNU și Linux, atunci codurile sunt cu siguranță deschise.

Ei bine, atunci când nu există drivere gratuite adecvate, atunci nu se poate face nimic, trebuie să instalați drivere proprietare. Dacă codurile lor sunt deschise depinde doar de producătorii de hardware.

Aplicații

Aplicații personalizate legate de categorie Sursa deschisa, sunt adesea fabricate în versiuni pentru diferite sisteme de operare. Nu fac parte din Linux. Adevărat, unele sunt standard pentru o anumită distribuție sau shell grafic, dar nu fac parte din nucleu.

Desigur, codurile pentru toate opțiunile sunt deschise - pentru toate sistemele de operare acceptate. Aceeași situație se întâmplă cu diverse utilități.

Cine o face

Nucleul Linux este îmbunătățit de un grup de entuziaști. Uneori participă însuși Linus Torvalds. Codul kernel-ului, ambalat într-o arhivă, poate fi descărcat de pe kernel.org pentru compilare independentă ulterioară.

Șoferii, dacă sunt liberi, sunt adesea făcuți și de comunități. Pentru imprimantă, scaner, placă video, Adaptor Wi-Fi... În general, există multe pentru ce.

De exemplu, pachetul Gutenprint, care este un set întreg de drivere pentru multe modele de imprimante. Mai mult, calitatea imprimării este adesea comparabilă cu indicatorii produși atunci când se folosesc drivere „native” de la producători.

Uneori, producătorii de hardware deschid codul sub o licență adecvată, cum ar fi GPL sau BSD. Astfel de evenimente provoacă de obicei o bucurie de nedescris în rândul susținătorilor Open Source.

După cum probabil ghiciți deja, aplicații personalizate sunt create, de asemenea, fie de către comunități, fie de către entuziaști individuali. Cu toate acestea, companiilor comerciale le place să facă publicitate, oferind populației o parte din produsele lor sub formă de Software Liber. Un exemplu izbitor: suite office OpenOffice.org a fost publicat de Oracle pentru o lungă perioadă de timp.

Mai mult, unele companii fac chiar și kituri de distribuție întregi. palarie rosie, SuSE, Xandros iau bani pentru ansambluri binare gata de utilizare, dar nu au dreptul de a ascunde codurile. Adică, aceste coduri, indiferent de modul în care sunt procesate, trebuie să rămână deschise. Aceasta este o cerință a licenței GPL.

Cine îl folosește

Un programator se uită la software și se gândește: „Este un lucru bun, dar se poate face mai bine!” Descarcă o arhivă cu cod de pe site-ul web al dezvoltatorului și o îmbunătățește. Lui i se alătură un grup de specialiști care doresc să participe și ia naștere un nou proiect.

Așa apar „furculițele” (din engleză „furculiță”, care în acest caz este tradusă ca „ramură”). Noi programe bazate pe baza de cod a celor existente.

De exemplu, de la player audio bun Amarok a făcut și mai bine - Clementine. Și din suita de aplicații de birou OpenOffice.org - LibreOffice, care se dezvoltă rapid și foarte promițător.

Deci, sistemele de operare întregi sunt clonate folosind acest principiu. Sistemul de operare CentOS gratuit este compilat din codurile sursă ale sistemului plătit Red Hat Enterprise Linux. Desigur, șefii de la Red Hat probabil își mușcă din coate de frustrare, dar nu pot face nimic, deoarece nu dețin codul sursă.

Cu toate acestea, în acest caz, modificarea se reduce în principal la decuparea logo-urilor înregistrate, dar fără deschiderea obligatorie a codului, însăși existența CentOS ar fi imposibilă în principiu.

Concluzie

Open source este un concept fundamental al Linux-ului în special și al întregului software liber în general. Codurile pot fi folosite pentru propriile proiecte, verificate pentru inofensivă prin eforturile comunității, studiate, îmbunătățite abilitățile prin participarea la dezvoltare, îmbunătățirea și asistarea oamenilor în cauza lor nobilă.

Nu există un ansamblu binar de software care să fie important pentru dvs. pentru o anumită distribuție GNU/Linux? Driverul nu este inclus în kernel? Am luat arhiva cu codul sursă, am despachetat-o, am citit instrucțiunile de asamblare, am compilat-o, am instalat-o - și am folosit-o. Nu depinzi de producător, nu ești legat de un anumit sistem de operare - aceasta este adevărata libertate.

Publicații anterioare:

Încărcarea oricărui sistem de operare modern este un proces complex în mai mulți pași. Procesul de pornire poate varia ușor între diferitele distribuții Linux, dar schema generala este aproximativ aceeași și constă din următoarele etape:

    Executați codul BIOS. Inițializarea echipamentelor. Alegere suport de pornire. Citirea bootloader-ului în RAM și transferarea controlului către acesta. Încărcătorul de pornire ocupă de obicei un sector de pe disc și este limitat ca dimensiune la 384 de octeți (512 de octeți - sector de disc, minus 128 de octeți - tabel de partiții). În funcție de tipul dispozitivului de pornire, sectorul de pornire poate fi citit din diferite locuri:

    • La pornirea de pe o dischetă sau un hard disk, bootloader-ul este citit din primul sector al suportului fizic;
    • La pornirea de pe un CD/DVD – din primul sector al imaginii disc de pornire, situat în structura de date CD;
    • La pornirea printr-o rețea, din primul sector al imaginii discului de pornire este descărcată de pe server prin protocolul tftp.

    Ecranul în această etapă afișează informații despre Versiunea BIOS, procesul de verificare a memoriei RAM, a găsit hard disk-uri. Codul încărcător de pornire este prea mic pentru a include funcționalitatea de imprimare a informațiilor, dar poate ieși mesaje scurte despre erori.

    Citirea bootloader-ului principal (GRUB, LiLo, NTLDR) în memorie și executarea codului acestuia. Deoarece bootloader-ul este foarte mic, de regulă, sectoarele din care trebuie citit codul principal de bootloader sunt codificate hard în codul său. Pe un HDD, acesta poate fi spațiul dintre MBR și prima partiție de pe disc (pista zero). Pe o dischetă și când se utilizează o imagine de disc la pornirea de pe un CD și prin rețea, bootloader-ul principal poate fi localizat imediat după bootloader-ul principal și poate ocupa întregul volum al imaginii.

    Se încarcă nucleul (vmlinuz) și imaginea discului auxiliar (initrd). Încărcătorul principal de pornire este suficient de inteligent pentru a găsi fișierul de configurare, fișierul imagine al nucleului și fișierul imagine al discului auxiliar în sistemul de fișiere. Dacă este necesar, imaginea nucleului este dezambalată în RAM și se formează o zonă de memorie care conține parametrii trecuți de la bootloader la kernel, inclusiv adresa imaginii discului auxiliar.

    Un disc auxiliar este necesar pentru modern sisteme Linux datorita modularitatii nucleului si contine driverele (ATA, NFS, RAID etc.) necesare pentru a avea acces la sistemul de fisiere principal.

    În această etapă se creează un proces cu pid=1, în care se execută scriptul init, aflat în directorul rădăcină al discului auxiliar. Opțiunile transmise nucleului sunt de fapt trecute la init ca argumente în linia de comandă.

    Scriptul conține descărcarea driverele necesare sub formă de module de nucleu, crearea de fișiere temporare de dispozitiv în directorul /dev pentru a accesa aceste module, scanarea partiții de disc pentru a detecta și inițializa RAID-uri și volume logice. După ce unitățile logice sunt inițializate, se încearcă montarea sistemului de fișiere rădăcină specificat de parametrul root=. În cazul fără disc pornire în rețea Se încearcă montarea directorului rădăcină prin NFS.

    Pe ecran apar mesaje despre încărcarea driverelor și căutarea volumelor virtuale ale subsistemului LVM. Etapa este finalizată prin remontarea directorului rădăcină pe sistemul de fișiere principal și încărcarea programului principal /sbin/init (sau echivalentul acestuia) în proces cu pid=1.

    În UNIX clasic și mai vechi versiuni Linux(până în 2012), programul init citește fișierul de configurare /etc/inittab, inițializează consolele text și pornește, de obicei, serviciile necesare folosind un set de scripturi situate în /etc/init.d și /etc/rc*.d directoare. Pe distribuțiile Linux moderne, fișierul /sbin/init conține mai mult de program modernîncepe serviciile. Cel mai popular dintre programe similare sunt parveniți și systemd, ceea ce poate reduce semnificativ timpul acestei faze de pornire.

    În această etapă, pe ecran sunt afișate linii care indică începerea serviciilor și informații despre succesul acestui proces ( sau ).

încărcător de pornire GRUB

Porniți de pe discul de instalare în modul Rescue. Pentru a face acest lucru, în momentul pornirii, la promptul de pornire: trebuie să introduceți Linux rescue

Dacă totul merge bine, directorul rădăcină al sistemului principal va fi montat în /mnt/sysimage, directorul de boot în /mnt/sysimage/boot. În plus, directoarele curente /proc, /sys și /dev vor fi montate în subdirectoarele corespunzătoare /mnt/sysimage. Dacă acest lucru nu se întâmplă, atunci va trebui să faceți aceste operațiuni manual.

Când toate directoarele sunt montate, puteți schimba directorul rădăcină

#dacă se dovedește că ați uitat să montați ceva, puteți ieși prin ^D chroot /mnt/sysimage

și reconstruiți initrd-ul

#copiați fișierul vechi cp -p /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r).img.bak #creați un nou dracut -f #dacă versiunea de kernel pe sistemul principal este diferit de versiunile de pe disc de instalare, specificați-l în mod explicit dracut -f /boot/initramfs-2.6.32-358.el6.x86_64.img 2.6.32-358.el6.x86_64

#copiați fișierul vechi cp -p /boot/initrd-$(uname -r).img /boot/initrd-$(uname -r).img.bak #creați unul nou mkinitrd -f -v /boot/initrd -$( uname -r).img $(uname -r) #dacă versiunea nucleului din sistemul principal diferă de versiunea de pe discul de instalare, specificați-o în mod explicit mkinitrd -f -v /boot/initrd-2.6.18- 371.el5.img 2.6. 18-371.el5

Cd/sync telinit 6

Exemplu complet cu driverul i2o_block (adaptorul SCSI Adaptec 2010S), care nu se încarcă automat. Exemplul rulează pe CentOS 5 deoarece nucleul standard CentOS 6 nu acceptă acest driver.

După pornirea de pe CD în modul Rescue, apare un mesaj că partițiile Linux nu au fost găsite și trebuie să le montați singur.

#Încărcați driverul insmod i2o_block #Verificați dacă totul a funcționat lsmod .... dmesg ... #Creați fișiere dispozitiv pe baza informațiilor din dmesg mkdir /dev/i2o mknod /dev/i2o/hda b 80 0 mknod /dev/i2o / hda1 b 80 1 mknod /dev/i2o/hda2 b 80 2 #Activate VolumeGroup lvm vgchange -a y #Mount volumes mkdir /mnt/sysimage mount /dev/mapper/VolGroup00-LogVol00 /mnt/sysimage mount //hda1i2 //hda1 / mnt/sysimage/boot #Mount directory special mount --bind /proc /mnt/sysimage/proc mount --bind /dev /mnt/sysimage/dev mount --bind /sys /mnt/sysimage/sys

În plus, conform instrucțiunilor, numai atunci când creați o imagine de disc, trebuie să specificați opțiunea suplimentară --preload=i2o_block în programul mkinitrd și să dezactivați serviciile readhead, deoarece conduc la înghețarea driverului i2o_block:

Chkconfig early-readahead dezactivat chkconfig later-readahead dezactivat

Ultima dată am vorbit despre ce se întâmplă când pornește Linux: mai întâi pornește încărcătorul de pornire, încarcă nucleul și instalează un disc temporar pe memorie cu acces aleator, nucleul începe procesul de init, init găsește discul rădăcină real, efectuează o revoluție atât de complicată - în loc de un disc virtual temporar, un disc real este montat în același loc în directorul rădăcină, de pe acest disc real se încarcă procesul de init. un alt init care este pe asta disc real. După toate aceste operațiuni, UNIX revine la starea normală de funcționare.

În această prelegere vă voi arăta ce face programul clasic init în combinație cu scripturile rc.d în stil System V. Sistemul V este varianta clasica UNIX pe care este construit UNIX comercial.

După cum sugerează și numele, rc.d este un director. Există o tradiție UNIX - dacă întreaga configurație a ceva se încadrează într-un singur fișier și se numește config, atunci când este împărțit în fișiere separate care sunt conectate la cel principal, creează un director cu același nume și adaugă config. .d la nume.d. Litera d înseamnă că acesta este un director și părțile auxiliare ale fișierului de configurare se află acolo. Formatul de fișier de configurare a programului init are două tradiții: varianta System V, în care fiecare detaliu de configurare este păstrat într-un fișier separat în directorul rc.d, și tradiția BSD, în care există un singur fișier /etc/rc care conține multe scripturi și variabile care sunt responsabile de comportamentul sistemului.

În orice caz, la pornirea sistemului, creăm un proces cu PID=1, în care se lansează un program numit init. După cum ați văzut ultima dată, dacă programul init este oprit, nucleul intră în panică și oprește orice lucru.

Classic System V init citește fișierul /etc/inittab și execută o serie de instrucțiuni care sunt scrise în acest fișier. Inittab este un fișier text, a cărui linie este, de fapt, o comandă sau un fel de regulă de comportament. Inittab arată astfel:

id:3:initdefault:

si::sysinit:/etc/rc.d/rc.sysinit

l3:3:wait:/etc/rc.d/rc 3

ca::ctrlaltdel:/sbin/shutdown -t3 -r acum

Există o etichetă la începutul liniei. Nu înțeleg cu adevărat care este marea semnificație a acestei etichete. Putem presupune că acesta este un text simplu și asta este tot. Al doilea punct este fie așa-numitul nivel de încărcare, fie valoare goală. Nivelul de încărcare este fie un singur număr de la 0 la 6, fie o listă de numere separate prin virgule. Urmează ceva acțiune. Acțiunile sunt următoarele: așteptați, respawn, sysinit, ctrlaltdel. Există și alte acțiuni, dar acestea sunt cele mai utilizate. În cele din urmă, la sfârșitul liniei există o anumită comandă scrisă cu numele fișierului executabil și argumentele care trebuie transmise acestei comenzi.

Acțiunea sysinit este executată o dată la pornirea sistemului.

Acțiunea ctrlaltdel nu este deloc o acțiune - este un handler pentru comanda rapidă de control alt del. Click-ul în sine este interceptat de nucleul sistemului, iar informațiile despre acesta sunt trimise procesului de inițiere, care trebuie să execute o comandă specifică. De exemplu, se poate lansa comanda de închidere, care va închide computerul. În principiu, puteți înregistra orice alt program aici, de exemplu, echo, care, după apăsarea control alt del, va emite un mesaj către toate terminalele sistemului. consolă pentru șemineu așa

Acțiunea de așteptare înseamnă că trebuie să rulați comanda, să așteptați până se termină și abia apoi să continuați procesarea următoarelor linii. Nu știu dacă astfel de acțiuni pot fi lansate în paralel. Cel mai probabil nu.

Acțiunea de reapariție înseamnă că trebuie să rulați programul și, fără a aștepta finalizarea acestuia, să treceți la acțiuni ulterioare. Dacă acest program se încheie ulterior, trebuie repornit.

Deci, există o singură execuție cu așteptarea rezultatelor și execuție multiplă în modul asincron - au început, au așteptat până s-a terminat, au lansat cuvintele.

Nivelurile de încărcare sunt o convenție care vă permite să controlați ce servicii sunt încărcate. Cel mai apropiat analog din Windows se încarcă în modul sigur, când se încarcă doar un număr limitat de drivere și încep un număr minim de servicii, se încarcă cu depanare, când fiecare acțiune este înregistrată suplimentar și o încărcare completă obișnuită.

Linux are în mod tradițional 6 opțiuni de pornire. Această împărțire este destul de arbitrară.

0 și 6 sunt oprite. 0 este o oprire completă, iar 6 este un mod de repornire.

4 este complet omis pe Linux

Au mai rămas patru niveluri de încărcare:

1 - modul pentru un singur utilizator. Dacă transmitem un singur cuvânt cheie la bootloader, ne vom găsi în modul single-user, unde rulează un singur proces și acesta este shell-ul administratorului de sistem. Acest mod este folosit pentru a restabili sistemul.

3 - modul text normal pentru mai mulți utilizatori, când toate serviciile rulează, rețeaua funcționează, toate driverele funcționează.

2 - și modul text, dar fără conectarea unităților de rețea. Faptul este acel fișier de rețea tradițional sistem nfs, care este folosit în UNIX, este extrem de rezistent la deteriorarea rețelei. Dacă am oprit serverul de fișiere sau am tăiat cablu de rețea, atunci sistemul de fișiere de rețea nfs va face numeroase încercări de recuperare și aceste încercări sunt atât de lungi încât nu am putut aștepta până când mesajul de eroare a apărut în sfârșit. Poate că asta se va întâmpla într-o oră, sau poate în 6 ore. În tot acest timp, driverul nfs va ține computerul, împiedicându-vă să faceți ceva. Prin urmare, dacă rețeaua sau serverul nostru de fișiere se blochează, setările spun că la pornire este necesară montarea unități externe, atunci încercarea va porni în modul complet va face totul să înghețe pentru tine. În acest caz, este furnizată a doua opțiune de pornire - totul este la fel ca în a treia, numai unitățile de rețea nu sunt conectate. Adaptorul de rețea în sine funcționează, adresa IP este atribuită, internetul este disponibil.

5 - la fel ca 3, dar cu lansarea ferestrei x - interfață grafică.

modul 2 include 1 + modul multiplayer. 3 permite montarea a 2+ sisteme de fișiere în rețea. În cele din urmă, 5 include 3 + lansare subsistem grafic. Dacă acest lucru va fi implementat în mod consecvent sau nu, este o problemă de distribuție. În general, administratorii pot configura în mod independent fișierul inittab astfel încât aceste moduri să fie lansate secvențial sau pot face totul complet independent - prin trecerea la următorul mod, eliminăm tot ce a fost făcut în pasul anterior și configuram totul de la zero.

Să ne uităm la rândurile unui fișier real. Sunt foarte simple.

l3:3:wait:/etc/rc.d/rc 3

Este lansat un program care ar trebui să facă totul acțiunile necesare, care sunt așteptate la al treilea nivel. Probabil, la al treilea nivel trebuie să configurați interfețele de rețea, să lansați driverul de terminal și să porniți unele servicii. Numai după ce toate acestea vor fi finalizate vom putea lucra în sistem. Deoarece trebuie să așteptăm finalizarea lansării, alegem acțiunea de așteptare.

Lansatorul se numește rc și este lansat cu numărul nivelului ca parametru. Programul init în sine este destul de simplu. Ea își poate citi fișierul rând cu linie cu o sintaxă simplă și poate începe noi procese prin lansarea unor programe auxiliare. Toată logica nivelului de încărcare este ascunsă în scriptul rc. Prin rularea rc cu parametrul 3 vom merge la al treilea nivel, cu parametrul 5 - la al cincilea.

Programul rc este, de asemenea, foarte simplu. Acesta este un script care execută toate fișierele din directoarele corespunzătoare nivelului de încărcare, de exemplu /etc/rc3.d/. Aceste directoare conțin fișiere executabile, care iau un parametru - fie pornire, fie oprire. Dacă fișierul este lansat cu parametrul start, atunci pornește serviciul, dacă cu parametrul stop îl oprește. De exemplu, pornirea rețelei va configura interfețele de rețea, iar oprirea rețelei va pune interfețele într-o stare dezactivată. Cu exceptia interfețe de rețea Există scripturi pentru conectarea/deconectarea sistemelor de fișiere din rețea, pornirea/oprirea serviciilor etc.

Numele fișierelor din directoare construite după anumite reguli. Ele încep fie cu litera K, fie cu litera S, urmată de un număr și de numele serviciului.

Scriptul rc caută prin conținutul directorului rc3 și selectează de acolo toate fișierele care încep cu litera K (kill). Fișierele sunt ordonate crescător și executate cu parametrul stop. Apoi se execută aceleași acțiuni cu fișierele care încep cu litera S (start), care sunt lansate cu parametrul start. Aceasta este, în general, întreaga procedură pentru trecerea la un anumit nivel.

Putem presupune că directorul /etc/rc0.d/ conține doar fișiere care încep cu litera K, deoarece totul trebuie oprit la închidere, iar directorul /etc/rc1.d/ va conține un fișier cu litera S pentru a lansa consola de administrator.

Pentru ușurința programării, există un director separat /etc/init.d/, care conține aceleași fișiere doar fără literele și numerele de la începutul numelui. De fapt, fișierele din directoarele de nivel sunt doar legături simbolice către fișierele principale. Deci /etc/rc3.d/S10apache este un link către fișierul /etc/init.d/apache. Sunt necesare litere și numere în numele legăturilor, astfel încât scriptul rc să le apeleze În ordinea corectă si cu argumentele necesare.

În sistemele care sunt construite pe acest principiu, pentru a porni sau opri orice serviciu din directorul /etc/init.d/, trebuie să găsiți fișierul care îi corespunde și să îl porniți cu parametrul start sau stop. Ce nu-i place la pornirea serviciilor în acest fel - prin apelarea explicită a scripturilor. Ideea este că în echipă linia linux Completarea automată funcționează excelent. Cu ajutorul acestuia puteți introduce foarte rapid calea către fișierul de pornire.

Pentru a ascunde o implementare specifică de utilizator, două programe auxiliare au fost scrise deasupra sistemului de scripturi și legături simbolice.

Programul chkconfig vă permite să manipulați legături simbolice la scripturile corespunzătoare. Pentru a vedea ce începe și ce se oprește la fiecare nivel, puteți folosi comanda ls și lista scripturile în directorul corespunzător, dar este mai ușor să utilizați comanda chkconfig –list. Programul chkconfig rulează prin toate directoarele rc și produce o listă cu ceea ce începe și ce se oprește la fiecare nivel. Dacă dorim ca un anumit serviciu să pornească automat când sistemul pornește, rulăm chkconfig<имя службы>on și scriptul creează o legătură pentru a rula în directorul dorit și cu nume corect. Rulați chkconfig<имя службы>off face ca legătura de pornire să fie eliminată și să fie creată legătura de oprire. Astfel, programul chkconfig vă permite să gestionați lista de servicii care pornesc la pornirea sistemului.

Un alt program - serviciu este folosit pentru a porni și opri manual serviciile. Service este un wrapper care vă permite să nu accesați direct scriptul, ci să specificați numele serviciului și să spuneți dacă vrem să-l pornim sau să îl oprim. Bash-ul pe care îl folosesc nu are completare automată pentru comanda de serviciu, așa că îmi este mai ușor să introduc calea către scripturi.

În scripturile de pornire, argumentele start și stop trebuie procesate. În plus, poți veni cu unele dintre propriile tale argumente care vor face ceva util.

Majoritatea scripturilor implementează o opțiune de stare, care arată dacă serviciul rulează sau nu. Când executăm start, scriptul, după ce a pornit cu succes serviciul, își primește PID-ul și îl scrie într-un anumit fișier. Comanda stop șterge fișierul. De obicei, astfel de fișiere sunt create în directorul /var/run/. Comanda status verifică dacă un astfel de fișier există. Dacă nu este acolo, raportează că serviciul nu rulează. Dacă fișierul există, extrage ID-ul procesului din acesta și verifică lista curentă de procese. Dacă acest identificator este prezent, totul rulează, dacă programul se defectează dintr-un anumit motiv, atunci starea indică faptul că a fost făcută o încercare de a porni acest serviciu - fișierul există, dar serviciul în sine nu rulează.

Opțiunea de repornire execută secvențial două comenzi în interiorul scriptului - mai întâi opriți, apoi porniți. Aceasta este o comandă complet opțională - doar convenabilă. În cele din urmă, există servicii care vă permit să recitiți din mers unele fișiere de configurare. Pentru ei, se adaugă o comandă de reîncărcare, a cărei sarcină este să trimită un semnal către serviciu că configurația s-a schimbat. Un caz separat, comenzile de salvare și încărcare pentru salvarea configurației firewall.

Dacă administratorul de sistem în loc să se oprească sau să pornească servicii individuale dorește să transfere întregul sistem la un anumit nivel, atunci acest lucru poate fi realizat în unul din două moduri. Puteți apela direct programul /sbin/init. Dacă o suni cu un anumit număr ca parametru, va executa toate instrucțiunile din fișierul inittab pentru care a fost specificat nivelul corespunzător. Dacă rulați, de exemplu, /sbin/init 1, atunci init va găsi în fișierul său de configurare toate liniile care conțin nivelul 1 și le va executa. Pe unele sisteme, comanda shutdown este implementată ca /sbin/init 0, deoarece nivelul 0 corespunde opririi sistemului. ÎN În ultima vreme Pentru a trece între niveluri, a apărut un program special numit telinit, care este o legătură către init. Sarcina sa este să trimită un semnal procesului de init că administratorul dorește să treacă la un anumit nivel. telinit q îi spune init să recitească fișierul inittab. În sistemele mai vechi, acest lucru a fost realizat prin trimiterea unui semnal SIGHUP către proces cu PID=1 (kill –HUP 1).

Încă câteva rânduri în inittab, aceasta este lansarea terminalelor

1:2345:respawn:/sbin/mingetty tty1

Pentru a oferi acces interactiv la sistem, este posibil să aveți o serie de linii de acest fel în inittabe. 2345 sunt nivelurile la care trebuie rulată comanda, respawn înseamnă că programul trebuie repornit dacă se termină. getty este un program de management al terminalelor. În mod tradițional, un terminal în UNIX se numește teletip deoarece primele terminale au fost mașini de scris electrice. Prin urmare, tty este o abreviere pentru teletypewriter. Mingetty este un program care poate funcționa cu terminale virtuale de pe un computer personal. Poate configura driverul terminalului, iar ca parametri primește numele dispozitivului terminal care trebuie configurat. În directorul /dev/ există un fișier de dispozitiv tty1, care corespunde primului terminal virtual. Dacă am avea un modem și am vrut să-l inițializam la boot, am putea apela getty cu parametrul ttyS0, care corespunde portului COM1. La inițializarea modemului, ar fi posibil să setați parametri suplimentari: viteza conexiunii 19200 baud, 7 sau 8 biți pe octet, paritate, număr de biți de oprire.

S0:2345:respawn:/sbin/getty ttyS0 19200 8 n 1

Ultima dată când am desenat un lanț în care un proces face o copie a lui însuși apelând fork, copia copil prin apelarea exec încarcă un alt program în memoria sa și, după finalizare, raportează acest lucru procesului părinte.

Sesiunile de utilizator text sunt organizate în următoarele lanțuri: mai întâi, init își face o copie și rulează programul mingetty în el. Mingetty inițializează terminalul și tastatura, apoi rulează programul de conectare în același proces. Conectarea afișează solicitări pentru introducerea unui nume și a unei parole și, dacă totul a mers bine, își atribuie privilegii de utilizator și, în același proces, suprascriindu-se, lansează un interpret de utilizator, de exemplu, bash. Când utilizatorul introduce comanda de ieșire, interpretul încheie calea de viață a acestui proces. Când un proces se termină, init primește un semnal despre el. Init se uită la ceea ce ar trebui să facă, vede acțiunea de respawn, rulează din nou programul mingetty, care reinițializează terminalul și repetă totul. Astfel, fiecare sesiune este în interiorul unui proces. De îndată ce am părăsit sesiunea, procesul nostru s-a încheiat și s-a lansat imediat un program care va curăța terminalul după noi și va restabili toate setările la implicite.

Există un alt cuvânt cheie special în fișierul inittab, initdefault - nivelul implicit. Dacă init a primit un singur parametru prin kernel, atunci vom porni la nivelul 1. Dacă nu a fost trecut nimic prin bootloader, atunci se folosește valoarea implicită. Dacă, după instalarea shell-ului grafic, se dovedește că computerul nostru este destul de slab pentru grafică, atunci putem seta nivelul implicit la 3, iar după următoarea repornire ne aflăm la al treilea nivel - adică în modul text. Am instalat sistemul fără modul grafic, apoi am instalat suplimentar toate pachetele pentru x window, am schimbat nivelul implicit la 5, iar după următoarea repornire am intrat direct în modul grafic.

În acest sistem de scripturi, uneori doriți să faceți ceva propriu, de exemplu, la pornire, ștergeți toate fișierele din directorul /tmp/. Pentru asta există dosar separat numit /etc/rc.local, care rulează după toate celelalte. Acesta este doar un script fără parametri în care puteți scrie orice doriți. De exemplu, pe unul dintre routerele mele, în momentul în care sistemul pornește, tabelele de rutare sunt scrise în acest fișier. Mi-a fost prea lene să caut unde se află scripturile standard corespunzătoare din distribuție și s-a dovedit a fi mai ușor să înregistrez comenzile în rc.local.

Imaginați-vă că aveți o imagine de kernel Linux pentru un telefon Bazat pe Android, dar nu aveți sursele corespunzătoare sau fișierele de antet ale nucleului. Imaginați-vă că nucleul are suport pentru încărcarea modulelor (din fericire) și doriți să construiți un modul pentru acel nucleu. Există mai multe motive bune pentru care nu poți să construiești un nou nucleu de la sursă și să-l lași așa (de exemplu, nucleul construit nu are suport pentru un dispozitiv important, cum ar fi un LCD sau un ecran tactil). Odată cu schimbarea constantă a ABI a nucleului Linux și lipsa fișierelor sursă și antet, ați putea crede că ați ajuns într-o fundătură.

Ca o afirmație de fapt, dacă construiți un modul kernel folosind fișiere antet diferite decât cele utilizate pentru a construi imaginea nucleului pe care o aveți, modulul nu va reuși să se încarce, cu erori în funcție de modul în care fișierele antet au fost diferite de ceea ce era necesar. Se poate plânge de semnături proaste, versiuni proaste si despre alte lucruri.

Configurația kernelului

Primul pas este să găsiți surse de kernel cât mai apropiate de imaginea nucleului. Probabil obținerea configurației corecte este cea mai dificilă parte a întregului proces de asamblare a modulului. Începeți cu numărul versiunii kernelului care poate fi citit din /proc/version . Dacă, ca mine, construiți un modul pentru dispozitive Android, încercați nucleele Android de la Code Aurora, Cyanogen sau Android, oricare dintre ele este cel mai apropiat de dispozitivul dvs. În cazul meu, a fost nucleul msm-3.0. Rețineți că nu trebuie neapărat să căutați exact aceeași versiune sursă ca și versiunea imaginii dvs. de kernel. Diferențe minore versiunile cel mai probabil nu vor fi o problemă. Am folosit sursele nucleului 3.0.21, în timp ce versiunea imaginii kernel-ului existent a fost 3.0.8. Cu toate acestea, nu încercați să utilizați sursele nucleului 3.1 dacă aveți o imagine kernel 3.0.x.

Dacă imaginea de kernel pe care o aveți este suficient de amabil să vă ofere un fișier /proc/config.gz, puteți începe cu asta, altfel, puteți încerca să începeți cu configurația implicită, dar în acest caz trebuie să fiți extrem de atenți ( În timp ce Nu voi intra în detalii despre utilizarea configurației implicite, deoarece am fost destul de norocos să nu trebuiască să recurg la ea, vor fi câteva detalii mai jos despre motivul pentru care configuratie corecta asa de important).

Presupunând că aveți arm-eabi-gcc disponibil într-una dintre căile din variabila de mediu PATH și că terminalul este deschis în folderul cu fișiere sursă kernel, puteți începe să configurați nucleul și să instalați fișiere de antet și scripturi:

$ mkdir build $ gunzip config.gz > build/.config # sau orice să pregătească .config $ make silentoldconfig pregăti scripturi headers_install ARCH=arm CROSS_COMPILE=arm-eabi- O=build KERNELRELEASE=`adb shell uname - r`
Versiunea silentoldconfig va întreba cel mai probabil dacă doriți să activați anumite opțiuni. Puteți alege valorile implicite, dar acest lucru s-ar putea foarte bine să nu funcționeze.

Puteți folosi altceva în KERNELRELEASE, dar trebuie să se potrivească exact cu versiunea kernel-ului din care intenționați să încărcați modulul.

Scrierea unui modul simplu

Pentru a crea un modul gol, trebuie să creați două fișiere: o sursă și un Makefile. Plasați următorul cod în fișierul hello.c, într-un director separat:

#include /* Este necesar pentru toate modulele */ #include /* Necesar pentru KERN_INFO */ #include /* Necesar pentru macrocomenzi */ static int __init hello_start(void) ( printk(KERN_INFO "Bună lume\n"); return 0; ) static void __exit hello_end(void) ( printk(KERN_INFO "La revedere lume\n"); ) module_init(hello_start); module_exit(hello_end);
Plasați următorul text într-un Makefile în același director:

Obj-m = salut.o
Asamblarea modulului este însă destul de simplă în această etapă modulul rezultat nu se va putea încărca.

Asamblarea modulelor

În timpul construcției normale a nucleului, sistemul de construire a nucleului creează un fișier hello.mod.c, al cărui conținut poate cauza diverse probleme:

MODULE_INFO(vermagic, VERMAGIC_STRING);
Valoarea VERMAGIC_STRING este determinată de macrocomanda UTS_RELEASE, care se află în fișierul include/generated/utsrelease.h generat de sistemul de construire a nucleului. În mod implicit, această valoare este determinată de versiunea kernelului și de starea depozitului git. Aceasta este ceea ce KERNELRELEASE stabilește la configurarea nucleului. Dacă VERMAGIC_STRING nu se potrivește cu versiunea kernelului, încărcarea modulului va avea ca rezultat un mesaj ca acesta în dmesg:

Bună ziua: versiunea magică „3.0.21-perf-ge728813-00399-gd5fa0c9” ar trebui să fie „3.0.8-perf”
În continuare, avem aici și o definiție a structurii modulului:

Struct modul __this_module __attribute__((section(".gnu.linkonce.this_module"))) = ( .name = KBUILD_MODNAME, .init = init_module, #ifdef CONFIG_MODULE_UNLOAD .exit = cleanup_module, #endif .arch );
În sine, această definiție pare inofensivă, dar structura modulului struct definită în include/linux/module.h are o surpriză neplăcută:

Modul Struct ( (...) #ifdef CONFIG_UNUSED_SYMBOLS (...) #endif (...) /* Funcția de pornire. */ int (*init)(void); (...) #ifdef CONFIG_GENERIC_BUG (.. .) #endif #ifdef CONFIG_KALLSYMS (...) #endif (...) (... multe mai multe ifdefs ...) #ifdef CONFIG_MODULE_UNLOAD (...) /* Funcția de distrugere */ void (*exit) ( void); (...) #endif (...) )
Aceasta înseamnă că, pentru ca pointerul init să ajungă în locul potrivit, CONFIG_UNUSED_SYMBOLS trebuie să fie definite în funcție de ceea ce folosește imaginea kernel-ului nostru. Ce zici de pointerul de ieșire, acestea sunt CONFIG_GENERIC_BUG , CONFIG_KALLSYMS , CONFIG_SMP , CONFIG_TRACEPOINTS , CONFIG_JUMP_LABEL , CONFIG_TRACING , CONFIG_EVENT_TRACING , CONFIG_FTRACE_MIG_LOD_MODULE și CONFIG_FTRACE_MILL_MODUL .

Începi să înțelegi de ce se presupune că de obicei folosim exact aceleași fișiere de antet cu care a fost creat kernel-ul nostru?

Static const struct modversion_info ____versions __used __attribute__((section("__versions")))) = ( ( 0xsomehex, "module_layout" ), ( 0xsomehex, "__aeabi_unwind_cpp_pr0" ), ( 0xsomehex "), ( 0xsomehex" ), ");
Aceste definiții provin din fișierul Module.symvers, care este generat în funcție de fișierele antet.

Fiecare astfel de intrare reprezintă simbolul cerut de modul și ce semnătură trebuie să aibă simbolul. Primul caracter, module_layout , depinde de cum arată modulul struct, adică depinde de opțiunile de configurare menționate mai devreme care sunt activate. A doua, __aeabi_unwind_cpp_pr0, este o funcție specifică ARM ABI, iar ultima este pentru apelurile noastre de funcție printk.

Semnătura fiecărui simbol poate diferi în funcție de codul nucleului pentru funcție și de compilatorul utilizat pentru a construi nucleul. Aceasta înseamnă că dacă construiți un nucleu din sursă, precum și module pentru acel nucleu și apoi reconstruiți nucleul după modificarea, de exemplu, a funcției printk, chiar și într-un mod compatibil, modulele construite inițial nu se vor încărca cu noul nucleu.

Deci, dacă construim un nucleu cu surse și configurații suficient de apropiate de cele care au fost folosite pentru a construi imaginea de kernel pe care o avem, există șansa să nu obținem aceleași semnături ca în imaginea kernel-ului și se va prăbuși atunci când incarcarea modulului:

Bună ziua: nu sunt de acord cu versiunea simbolului nume_simbol
Ceea ce înseamnă că avem nevoie de fișierul Module.symvers corect pentru imaginea kernelului, pe care nu îl avem.

Studiind nucleul

Deoarece nucleul efectuează aceste verificări la încărcarea modulelor, acesta conține, de asemenea, o listă de simboluri pe care le exportă și semnăturile corespunzătoare. Când nucleul încarcă un modul, parcurge toate simbolurile pe care modulul le solicită pentru a le găsi în tabelul său de simboluri (sau în alte tabele de simboluri ale modulelor pe care le utilizează modulul) și pentru a verifica semnăturile corespunzătoare.

Nucleul folosește următoarea funcție pentru a căuta în tabelul de simboluri (în kernel/module.c):

Bool every_symbol_section(bool (*fn)(const struct symsearch *arr, struct module *owner, void *data), void *data) ( struct module *mod; static const struct symsearch arr = ( ( __start___ksymtab, __stop___ksymtab, __stop___ksymtab, _PL_tabLY,__Gc_start, _PL_STARTLY , false ), ( __start___ksymtab_gpl, __stop___ksymtab_gpl, __start___kcrctab_gpl, GPL_ONLY, false ), ( __start___ksymtab_gpl_future, __stop___ksymtab_gpl_future, _rc_tab_future_, _rc_tab_future_PL_ NUMAI, false ), #ifdef CONFIG_UNUSE D_SYMBOLS ( __start___ksymtab_unused, __stop___ksymtab_unused, __start___kcrctab_unused, NOT_GPL_ONLY, true ), ( __start___ksymtab_top_uns_pl_,unus_g start___kcrctab_unused_gpl , GPL_ONLY, true ), #endif , if (each_symbol_in_section(arr, ARRAY_SIZE(arr), NULL, fn, data)) returnează adevărat (...)
Structura utilizată în această funcție este definită în include/linux/module.h:

Struct symsearch ( const struct kernel_symbol *start, *stop; const unsigned long *crcs; enumerare ( NOT_GPL_ONLY, GPL_ONLY, WILL_BE_GPL_ONLY, ) licență; bool neutilizat; );
Notă: acest cod nucleul nu s-a schimbat semnificativ în ultimii patru ani (se pare că de la lansarea nucleului 3.0 în cauză - aprox.).

Ceea ce avem mai sus în funcția each_symbol_section sunt trei (sau cinci când CONFIG_UNUSED_SYMBOLS este activat) câmpuri, fiecare conținând începutul tabelului de simboluri, sfârșitul acestuia și două steaguri.

Aceste date sunt statice și persistente, ceea ce înseamnă că vor apărea în binarul kernel așa cum sunt. Scanând nucleul pentru trei secvențe succesive de trei pointeri în spațiul de adrese kernel, urmate de valori întregi din definițiile din fiecare_secțiune_simbol, putem determina locația tabelelor de simboluri și semnături și putem recrea fișierul Module.symvers din nucleu. binar.

Din păcate, majoritatea nucleelor ​​de astăzi sunt comprimate (zImage), așa că o simplă căutare printr-o imagine comprimată nu este posibilă. Nucleul comprimat este de fapt un mic binar urmat de un flux comprimat. Puteți scana un fișier zImage pentru a găsi fluxul comprimat și a extrage imaginea decomprimată din acesta.

Etichete: Adăugați etichete

Aud adesea oameni referindu-se la nucleul Linux ca un exemplu de nucleu Linux și nu găsesc niciun răspuns pe niciun motor de căutare despre motivul pentru care se numește imagine.

Când mă gândesc la imagine, Mă pot gândi doar la două lucruri, fie o copie a discului, fie o fotografie. Bineînțeles că nu este o imagine fotografică, la naiba, așa că de ce se numește imagine?

5 Soluții colectează formulare web pentru „De ce nucleul Linux este numit „imagine”?”

Procesul de boot Unix a avut doar oportunități limitateîncărcare inteligentă a programelor (mutare, încărcare biblioteci etc.). De aceea programul original era imaginea exactă stocată pe disc, cea care trebuia încărcată în memorie și „apelată” pentru a obține nucleul.

Nu a fost decât mult mai târziu când au fost adăugate lucruri precum (de-comp) și, deși acum sunt instalate încărcătoare mai puternice, numele imaginii este blocat.

Cuvântul imagine are, de asemenea, definiția „Un fișier care conține toate informațiile necesare pentru a crea o copie vie de lucru”.

Acest lucru nu înseamnă că „imaginea” este doar o copie 1:1 a discului. Pentru că fotografia reprezintă realitatea exact Asa de la fel, ca într-un instantaneu, o imagine a unui program executabil (sau nucleu) reprezintă programul într-o stare în care poate fi încărcat (sau dezambalat) în memoria sistemului exact, așa cum este și apoi i s-a acordat controlul asupra lui. Acest program poate fi apoi lansat din această stare într-o manieră consecventă. Astfel, o imagine a nucleului Linux este o imagine (imagine de stare) a nucleului Linux care poate rula pe cont propriu, dându-i control.

În prezent, descărcatorul încarcă o astfel de imagine din Sistemul de fișiere hard disk(se cere șofer), îl înlocuiește și, prin urmare, îi oferă controlul. Procesul de pornire a computerului are loc de mai multe ori până când sistemul de operare începe să funcționeze. Aceasta se numește încărcare în lanț. Sau, dacă un program mai mic (lanț) încarcă unul mai complex, se numește bootstrapping.

BIOS-ul încarcă bootloader-ul, care este și o imagine, de exemplu boot.img în case grub. Acest boot.img nu este un fișier (dacă este instalat grub); acesta este numele pentru partea care este în principal intrare de boot(MBR). Dacă încărcați un fișier într-un fișier, acesta va fi o imagine ca fișier și nu va fi scris HDD, dar scris într-un fișier. Este, de asemenea, o reprezentare (imagine) a celei mai vechi stări în care grub poate încărca restul. grub are apoi propriul mecanism pentru cum să se pornească complet în timp ce încarcă alte imagini. Aceasta este reprezentată de diferite etape în grub. Bootloader-ul încarcă apoi imaginea kernel-ului, înlocuindu-se cu conținutul extras din acel fișier.

Istoria antica. termenul „imagine” provine de la vechiul termen „Digital Equipment Corporation” pentru compilator->ieșire linker. un fișier este o imagine creată prin interpretarea codului etc., printr-un linker pentru a crea o „imagine” executabilă a designului tău.

În matematică, nucleul este imaginea inversă a unui submulțime a imaginii unei mapări, indiferent dacă submulțimea a fost egală cu elementul de identitate din codomeniu. Sunt sigur că aceste nume sunt derivate din concepte matematice, deoarece sunt legate semnificativ în diferite domenii ale matematicii. Având în vedere că Unix a fost derivat dintr-un mediu academic, este posibil ca utilizarea acestui nucleu și imaginea acestor cuvinte să fie aceleași.

Dacă aveți o mulțime care reprezintă un anumit nivel de informații despre sistemul de operare „complet”, dacă informațiile respective formează și un grup, atunci puteți defini un homomorfism de grup pe acea mulțime sau, practic, puteți mapa cu alte mulțimi care au marimi diferite, apoi setul original dacă „respectează” structura set original, ceea ce a făcut din ea un grup. Puteți vedea ce ar putea fi omis pentru a potrivi un set cu un set mai mic sau cu un subset al unui set în care subsetul este mai mic.

Imagine. Imaginea homomorfismului de grup și funcții generale iar mapările sunt doar un subset al unui set ale cărui elemente sunt de fapt comparate. Este posibil ca caracteristica să nu fie afișată pentru fiecare element și acele elemente nu vor fi incluse în imagine.

Nucleul este practic doar elemente din set original, care se mapează la o imagine, dar afișează doar elementul de identitate al imaginii. Practic elemente care afișează 0 ca lucrul din imagine.

Dacă imaginea este mai mică decât setul original, atunci putem vedea că mai multe elemente trebuie mapate la un singur element. Deci, de exemplu, ar putea exista mai multe elemente din nucleu care se mapează la o imagine și știm deja că ar trebui să se mapeze toate la 0.

Putem vedea că dacă alegem ca mulțimea originală să fie secvențe finite de binare sau 1 și 0, iar codomeniul (mulțimea mapată la) sunt, de asemenea, secvențe de binare, atunci putem construi astfel de lucruri dacă și numai dacă o structură de grup adecvată. poate fi definit (acesta este un pic mai profund și nu are legătură cu întrebarea).

Prin urmare, vedem cu deplină încredere că „nucleul” și „imaginea” sistemului de operare sunt complet definite și au sens matematic. Indiferent poate de alte utilizări ale termenilor.