Procesul de initializare al unui sistem Slackware GNU/Linux
From linux360
Primul pas catre atingerea rangul de administrator de sistem nu este configurarea serverului X, nici jonglatul cu un parafoc, ci intelegerea procesului de demarare al unui sistem de operare si de initializare a serviciilor oferite de acesta. Odata inteles acest proces, se poate fasona profilul sistemului si se pot alege serviciile care se doresc a fi pornite, de abia dupa care atentia poate fi focalizata catre configurarea unui serviciu anume.
In continuare, voi incerca sa explic, sumar, demararea sistemului de operare GNU/Linux si, in detaliu, procesul de initializare al unui sistem bazat pe distributia Slackware.
Contents
Cu ce ar trebui sa fie familiarizat cititorul
Pornind de la premiza ca interactioneaza/a interactionat cu sistemul de operare GNU/Linux, distributia fiind irelevanta, cititorul ar trebui sa fie familiarizat cu urmatoarele:
- notiuni elementare in ceea ce priveste geometria unui hard-disc
- conceptul de nucleu linux ( Preferabil sa-l fi configurat si compilat macar o data. )
- experienta cu interpretatorul de comenzi BASH, precum si modul in care acesta poate fi folosit pentru scriptare
- deprindere in intrebuintarea paginilor manual
- notiuni de baza ale limbajului de programare C
[...de completat pe parcurs..]
Observatii:
- Toate paginile manual din acest ghid sint din cadrul distributiei Slackware 11.0; unele dintre ele n-o sa existe pe alte distributii, iar daca exista, sansele sint sa difere, dat fiind faptul ca voi acoperi subiecte care sint, de obicei, specifice unei distributii.
[...de completat pe parcurs.]
Cuprins
Conform paginii manual boot(7), secventa de demarare difera de la un sistem la sistem, dar poate fi impartita, pe scurt si incomplet, in urmatoarele stagii:
- Demararea fizica
- Incarcarea nucleului
- Initializarea sistemului si a serviciilor
Demararea Fizica
Procesul de demarare fizica al unui calculator este dependent de arhitectura microprocesorului. In cazul de fata, aceasta arhitectura va fi x86/x86-compatibila. Procesul este unul complex, dar poate fi rezumat in felul urmator:
- La pornirea sursei de alimentare, memoria primara a sistemului(memoria cu acces aleatoriu — engl.: RAM) este goala, asa ca microprocesorul este programat sa execute instructiunile situate intr-o zona rezervata(FFFF0h) a memoriei numai-citire(engl. presc. ROM) a sistemului de intrare/iesire pe baza(engl.presc. BIOS). Scopul acestei zone este de a directiona microprocesorul catre locatia unde se afla programul BIOS.
- Odata ce BIOSul este incarcat in memorie, acesta efectueaza mai multe operatii: autotestarea la punerea in functiune(engl. presc. POST), initializarea/inventar al dispozitivelor s.a.
- Catre final, BIOSul cauta o unitate de disc de pe care sa demareze. De obicei, aceasta unitate de disc este selectionata in prealabil de catre utilizator si poate fi un CD-ROM, o unitatea de dischete, un hard disc.. In cazul acesta o sa fie de hard disc, caci se presupune ca sistemul este deja instalat in memoria fizica.
- Cand gaseste unitatea de disc, ii incarca si executa sectoru de demarare(engl. boot sector), care, in cazul de fata, fiind vorba de un hard disc, poarta numele de MBR(Master Boot Record) si este localizat in primul sector al hard discului(primii 512 byti). Din momentul acesta, controlul este predat codului din MBR.
Incarcarea nucleului
Acest al doilea stagiu are ca scop principal incarcarea in memorie a nucleului de pe hard disc si executarea acestuia. Solutionarea poate fi abordata in mai multe moduri:
- Poate fi folosit un program de incarcare(engl. bootloader) independent de nucleu. Cele mai populare in mediul GNU/Linux sint LILO si GRUB.
- Nucleul poate fi lasat sa se autoincarce si autoexecute.
Ambele solutii au in comun faptul ca se folosesc de primul sector din MBR pentru a isi pune in functiune mecanismul, deoarece codul din primul sector al MBRului hard discului este primul care va fi executat la in acest stagiu.
Astazi, in mediul calculatoarelor personale, a doua metoda este foarte rar intrebuintata, date fiind avantajele folosirii unui program de incarcare independent de nucleu. Dintre aceste avantaje, cele mai important de mentionat ar fi: posibilitatea de-a rula mai multe sisteme de operare pe acelasi calculator si posibilitatea de-a trimite parametrii de executie nucleului. Problema este ca aceste beneficii, dupa cum vom vedea putin mai tarziu, pot aduce (mari) riscuri de securitate.
Urmeaza o scurta explicatie a mecanismului celor doua metode.
Programul de incarcare(GRUB/LILO)
Aceasta metoda se imparte, la randul ei, in mai multe stagii, datorita limitarilor impuse de componentele hard. Daca se va opta pentru folosirea unui program de incarcare, odata cu instalarea acestuia, primul sector al MBRului va fi ocupat de de programul de incarcare primar(engl. primary boot loader), contine un set de instructiuni, un tabel cu partitii(maximum 4 primare, dintre care una poate fi extinsa). si, la final, un numar 'magic'(0xAA55) folosit pentru validarea continutului. Acesta este primul stagiu, iar scopul lui este sa verifice tabelul cu partitii pentru partitii active, iar in cazul vreunei descoperiri, sa incarce in memorie continutul sectorului de incarcare al respectivei partitii si sa-l execute.
Stagiul al doilea(care poate fi, de asemenea, fractionat) difera de la program de incarcare la program de incarcare, dar scopul lui este sa incarce in memorie imaginea nucleului(doar este arhivat cu gzip, nu?), sa-l dezarhiveze si sa-l execute cu sau fara parametrii de executie specificati de catre utilizator. Pentru mai multe detalii, consultati sfirsitul ghidului.
Autoincarcarea si autoexecutarea nucleului
[...]m-am gandit si cred ca nu ar merita detaliata..., mm...??!1111
Initializarea sistemului si a serviciilor
Odata executat, nucleul, printre altele, initializeaza si seteaza dispozitivele hard, memoria, monteaza sistemul de fisiere radacina s.a. Daca doriti sa stiti mai multe informatii despre acest proces, verificati sfirsitul ghidului.
In final, nucleul executa comanda init (sau cea prestabilita prin intermediul programului de incarcare), prin care initializarea sistemului este pornita. Pentru a exemplifica, am sa postez _finalul_ fisierului sursa init/main.c:
/* * We try each of these until one succeeds. * * The Bourne shell can be used instead of init if we are * trying to recover a really broken machine. */ if (execute_command) run_init_process(execute_command); run_init_process("/sbin/init"); run_init_process("/etc/init"); run_init_process("/bin/init"); run_init_process("/bin/sh"); panic("No init found. Try passing init= option to kernel.");
Dupa cum observam, init este primul(chiar unicul) program executat de catre nucleu. De fapt, nucleul nu executa _programul_ init, ci programul care are calea absoluta /sbin/init, /etc/init, /bin/init sau /bin/sh, asta in cazul in care nucleului nu-i este specificat ca parametru de executie(init= -- deobicei specificat prin intermediul lui LILO sau altui program de incarcare) altceva(execute_command).
Mai observam ca dupa 3 incercari de a executa programul "init", nucleul isi incearca pentru ultima oara norocul cu /bin/sh. Pe Slackware (si nu numai), fisierul cu aceasta cale absoluta este o legatura cu interpretorul de comenzi BASH. Asta inseamna ca, in cazul in care celelalte trei cai nu sint valide, ne vom trezi cu un interpretor de comenzi pentru suprautilizator si un sistem neconfigurat. Acesta este unul dintre riscurile de securitate despre care vorbeam in subcapitolul legat de programele de incarcare, datorita faptului ca prin intermediul lor se poate forta nucleul sa execute calea /bin/sh, sau a oricarui alt executabil preprogramat. Folosindu-ne de cunostintele acumulate pe parcursul ghidului, voi arata, catre final, in capitolul [inca nu i-am gasit un nume] cum se poate configura si pune in picioare in mod manual un sistem folosindu-ne doar de interpetatorul de comenzi.
Tot procesul descris pana in acest moment ar trebui sa fie independent de distributia folosita. In schimb, odata cu executia programului cu una dintre cele 3 cai enumerate mai devreme, lucrurile tind sa devina specifice (dar nu exagerat) distributiei, sau, mai exact, specifice unui stil de initializare.
Lumea tinde sa-i atribuie lui Slackware si derivatelor sale stilul "BSD", iar distributiilor ca Fedora Core, SuSe, Mandriva s.a. stilul "System V". BSD si System V au fost, acum multi ani, niste versiuni de UNIX care, dupa cum se vede, au influentat sistemele de operare actuale. Ele isi mai continua si astazi existenta prin rudele lor de grad I, cum ar fi, in cazul lui System V, UnixWare, iar, in cazul lui BSD, Open/Net/FreeBSD.
Aceasta categorisire, in schimb, daca este luata la puricat, nu este tocmai corecta. Slackware se foloseste de stilul de initializare "System V", doar ca il abordeaza intr-o maniera 'mai BSD', simplificandu-l, dupa cum vom vedea. Nu am sa intru detalii legate de diferentele de abordare a initializarii de catre, sa zicem, Mandriva si Slackware, nu asta este scopul ghidului. In schimb, la final, odata inteles modul in care Slackware 'vede lumea', cititorul se poate folosi de cunostiintele acumulate pentru a compara toate distributiile GNU/Linux, daca doreste :~)
sysvinit
Slackware, ca si majoritatea celorlalte distributii, se foloseste de suita de utilitare sysvinit (instalata prestabilit). O scurta descriere a pachetului, insotita de o lista cu programele incluse in el, ar fi urmatoarea:
err@coliba:~$ echo -e \\n "Descriere:"; head -n14 /var/log/packages/sysvinit-2.84-i486-69; \ echo -e \\n\\n "Lista cu programe:"; grep -e [18].gz$ /var/log/packages/sysinit-2.84-i486-69 | \ awk -F/ ' { print $4 } ' | awk -F. ' { print $1 } ' Descriere: PACKAGE NAME: sysvinit-2.84-i486-69 COMPRESSED PACKAGE SIZE: 296 K UNCOMPRESSED PACKAGE SIZE: 650 K PACKAGE LOCATION: /var/log/mount/slackware/a/sysvinit-2.84-i486-69.tgz PACKAGE DESCRIPTION: sysvinit: sysvinit (init, the parent of all processes) sysvinit: sysvinit: System V style init programs by Miquel van Smoorenburg that control sysvinit: the booting and shutdown of your system. These support a number of sysvinit: system runlevels, each with a specific set of utilities spawned. sysvinit: For example, the normal system runlevel is 3, which starts agetty sysvinit: on virtual consoles tty1 - tty6. Runlevel 4 starts xdm. sysvinit: Runlevel 0 shuts the system down. sysvinit: Lista cu programe: last runlevel killall5 shutdown poweroff init halt pidof reboot telinit
Observam ca unul dintre programele incluse in pachet poarta denumirea de init. II aflam calea absoluta:
err@coliba:~$ su -c 'which init' Password: /sbin/init
Avand respectiva cale, inseamna ca ar trebui sa fie primul program executat de nucleu. Ne putem convinge de acest lucru folosind comanda pstree(1), care ne va afisa un arbore de procese.
err@coliba:~$ pstree -np init(1)-+-keventd(2) |-ksoftirqd_CPU0(3) |-kswapd(4) |-bdflush(5) |-kupdated(6) |-khubd(7) |-syslogd(72) |-klogd(75) |-inetd(631) |-dhcpcd(635) |-sshd(639) |-crond(652) |-atd(654) |-gpm(664) |-agetty(667) |-agetty(668) |-agetty(669) |-agetty(670) |-agetty(671) |-bash(860)---startx(958)---xinit(974)-+-X(975) | `-xinitrc(979)---startkde(980)---kwrapper(1020) |-kdeinit(1008)-+-kdeinit(1013) [...]
Uitandu-ne la arbore, observam ca, pe langa faptul ca init este primul proces si are pid'ul(tradus?) 1, restul proceselor tind sa izvoreasca din el. Consultandu-i pagina manual (init(8)), aflam niste detalii importante, printre care:
- Init este tatal tuturor proceselor. Este primul program executat de catre nucleul la sfarsitul secventei de initializare al acestuia, fiindu-i atribuit pid-ul cu valoarea 1. ( de mentionat ca nucleul n-are pid'ul 1, ci 0. )
- Printre scopurile sale se numara: Initializarea tuturor celorlalte procese, colectarea proceselor moarte(zombi) si regenerarea unor procese fiu la terminarea lor; Inspectarea, la initializare, a fisierului /etc/inittab, pentru configurarea sistemului.
- Acceptare unor parametrii de executie, de obicei setati prin intermediul unui program de incarcare, care, daca sint specificati, ii pot schimba cursul firesc al derularii.
- Captarea unor semnale si reactionarea la ele.
Restul capacitatilor vor fi descrise spre finalul ghidului.
/etc/inittab
Dupa cum s-a specificat mai sus, init,la executare, va citi fisierul /etc/inittab pentru a sti cum sa configureze sistemul. Conform paginii manual inittab(5), formatul fisierului /etc/inittab este urmatorul:
id:niveluri de rulare:actiune:proces
- Campul id: Trebuie sa contina un sir unic de maximum 4 caractere alfanumerice. Este folosit pentru a identifica fiecare intrare din fisier.
- Niveluri de rulare: In primul rand, nivelul de rulare, conform paginii manual init(8), reprezinta o configuratie software a sistemului care, printre altele, specifica ce procese trebuiesc pornite de catre init. Configuratia se realizeaza prin intermediul unor scripturi BASH, fiecarui nivel de rulare atribuindu-se cel putin unul. Pot exista mai multe niveluri de executie. In Slackware, cele prestabilite sint urmatoarele:
# These are the default runlevels in Slackware: # 0 = halt # 1 = single user mode # 2 = unused (but configured the same as runlevel 3) # 3 = multiuser mode (default Slackware runlevel) # 4 = X11 with KDM/GDM/XDM (session managers) # 5 = unused (but configured the same as runlevel 3) # 6 = reboot
In fisierul /etc/inittab, campul dedicat nivelurilor de rulare trebuie sa contina o lista de niveluri de rulare pentru care trebuie executata o actiune ce, in majoritatea cazurilor. Vom vedea imediat ce inseamna toate acestea.
- Campul actiune: Descrie actiunea pe care init o sa o realizeze pentru o lista de niveluri de rulare. Exista mai multe tipuri de actiuni, printre care:
respawn: lanseaza o noua instanta a unui proces, daca acesta isi termina executia
wait: procesul va fi pornit odata cu intrarea in nivelul de rulare, iar init va astepta pana acesta se incheie.
once: procesul va fi executat o singura data, de indata ce se va intra in nivelul de rulare
sysinit: intrarea ce contine aceasta actiune specifica procesul ce trebuie executat in timpul initializarii sistemului de catre init. De obicei, acest, dupa cum vom vedea, scriptul BASH /etc/rc.S.
initdefault: intrarea ce contine aceasta actiune specifica si nivel de rulare care va fi executat de catre init, imediat dupa ce sistemul a fost initializat (prin intermediul scriptului rc.S.)
ctrlaltdel: procesul va fi executat atunci cand init va primi semnalul SIGINIT. Semnalul SIGINIT este trimis atunci cand sint apasate tastele CTRL-ALT-DELETE.
Dupa cum se observa, majoritatea actiunilor merg mana in mana cu un proces. Procesul este specificat in campul proces.
- Campul proces: Specifica un proces ce trebuie executat la intrarea intr-un nivel de rulare. Procesul poate fi o comanda sau un script.
Ca sa intelegem mai bine ce inseamna toate acestea, vom analiza un fisier /etc/inittab.
err@coliba:~$ cat -n /etc/inittab 1 # 2 # inittab This file describes how the INIT process should set up 3 # the system in a certain run-level. 4 # 5 # Version: @(#)inittab 2.04 17/05/93 MvS 6 # 2.10 02/10/95 PV 7 # 3.00 02/06/1999 PV 8 # 4.00 04/10/2002 PV 9 # 10 # Author: Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org> 11 # Modified by: Patrick J. Volkerding, <volkerdi@slackware.com> 12 # 13 14 # These are the default runlevels in Slackware: 15 # 0 = halt 16 # 1 = single user mode 17 # 2 = unused (but configured the same as runlevel 3) 18 # 3 = multiuser mode (default Slackware runlevel) 19 # 4 = X11 with KDM/GDM/XDM (session managers) 20 # 5 = unused (but configured the same as runlevel 3) 21 # 6 = reboot 22 23 # Default runlevel. (Do not set to 0 or 6) 24 id:3:initdefault: 25 26 # System initialization (runs when system boots). 27 si:S:sysinit:/etc/rc.d/rc.S 28 29 # Script to run when going single user (runlevel 1). 30 su:1S:wait:/etc/rc.d/rc.K 31 32 # Script to run when going multi user. 33 rc:2345:wait:/etc/rc.d/rc.M 34 35 # What to do at the "Three Finger Salute". 36 ca::ctrlaltdel:/sbin/shutdown -t5 -r now 37 38 # Runlevel 0 halts the system. 39 l0:0:wait:/etc/rc.d/rc.0 40 41 # Runlevel 6 reboots the system. 42 l6:6:wait:/etc/rc.d/rc.6 43 44 # These are the standard console login getties in multiuser mode: 45 c1:1235:respawn:/sbin/agetty 38400 tty1 linux 46 c2:1235:respawn:/sbin/agetty 38400 tty2 linux 47 c3:1235:respawn:/sbin/agetty 38400 tty3 linux 48 c4:1235:respawn:/sbin/agetty 38400 tty4 linux 49 c5:1235:respawn:/sbin/agetty 38400 tty5 linux 50 c6:12345:respawn:/sbin/agetty 38400 tty6 linux 51 52 # Runlevel 4 used to be for an X window only system, until we discovered 53 # that it throws init into a loop that keeps your load avg at least 1 all 54 # the time. Thus, there is now one getty opened on tty6. Hopefully no one 55 # will notice. ;^) 56 # It might not be bad to have one text console anyway, in case something 57 # happens to X. 58 x1:4:respawn:/etc/rc.d/rc.4 59 60 # End of /etc/inittab
Vom analiza fiecare intrare, explicand-o.
Prima intrare, cea de la linia 24, are urmatoarele calitati: Este identificata prin sirul de caractere "id" (datorita campului id, faptul ca valoare campului coincide cu numele acestuia nu are vreo importanta). Campul nivelului de rulare este ocupat de caracterul "3". Campul actiunii este ocupat de 'initdefault', ceea ce inseamna ca init va intra in nivelul de rulare specificat de catre acest camp, adica, in cazul nostru, "3". Campul proces lipseste doarece intrarea, continand actiunea 'initdefault', nu necesita un proces, acesta fiind oricum ignorat daca ar fi specificat.
A doua intrare, cea de la linia 27, are urmatoarele calitati: Este identificata prin sirul de caractere "si". Campul nivelului de rulare este ocupat de caracterul "S".Campul actiunii este ocupat de catre "sysinit", iar procesul este scriptul /etc/rc.d/rc.S. Faptul ca "sysinit" ocupa campul actiune ii spune lui init sa execute procesul din campul proces (in cazul acest, ii spune lui init sa execute scriptul /etc/rc.d/rc.S) inainte de a intra in vreun nivel de rulare(nivelul "3", in cazul nostru ^^).
A treia intrare, cea de la linia 30, are urmatoarele calitati: Este identificata prin sirul de caractere "su". Campul nivelului de rulare este "1S", ceea ce-nseamna ca intrarea se aplica atat nivelului de rulare "1", cat si nivelului de rulare "S". Campul actiunii este ocupat de catre "wait", iar procesul de catre scriptul /etc/rc.d/rc.K. Faptul ca "wait" ocupa campul actiune ii spune lui init sa execute scriptul /etc/rc.d/rc.K atunci cand va intra in oricare dintre nivelurile de rulare specificate in campul nivelului de rulare. De asemenea, init trebuie sa astepte pana ce scriptul va termina tot ce are de facut.
A patra intrare, cea de la linia 33, are urmatoarele calitati: Este identificata prin sirul de caractere "rc". Campul nivelelor de rulare este "2345", ceea ce inseamna ca intrarea se aplica nivelelor de rulare "2", "3", "4" si "5". Campul actiunii este ocupat de catre "wait", iar procesul de catre scriptul /etc/rc.d/rc.M. Faptul ca "wait" ocupa campul actiune ii spune lui init sa execute scriptul /etc/rc.d/rc.K atunci cand va intra in oricare dintre nivelurile de rulare specificate in campul nivelului de rulare. De asemenea, init trebuie sa astepte pana ce scriptul va termina tot ce are de facut.
A cincea intrare, cea de la linia 36, are urmatoarele calitati: Este identificata prin sirul de caractere "ca". Campul nivelelor de rulare este gol. Campul actiunii este ocupat de catre "ctrlaltdel", iar procesul de catre comanda "/sbin/shutdown -t5 -r now". Faptul ca "ctrlaltdel" ocupa campul actiune ii spune lui init ca, atunci cand sint apasate tastele CTRL+ALT+DELETE la consola, sa execute procesul din campul proces, in cazul nostru comanda "/sbin/shutdown -t5 -r now". Aceasta actiune nu necesita un nivel de rulare, presupunandu-se ca, daca ajungem la o consola sa apasam cele trei taste mai devreme mentionate, sintem deja intr-un nivel de rulare cu un sistem mai mult sau mai putin configurat.
A sasea intrare, cea de la linia 39, are urmatoarele calitati: Este identificata prin sirul de caractere "l0". Campul nivelelor de rulare este ocupat de catre "0", ceea ce inseamna ca intrarea se aplica nivelului de rulare "0". Campul actiunii este ocupat de catre "wait", iar procesul de catre scriptul /etc/rc.d/rc.0. Faptul ca "wait" ocupa campul actiune ii spune lui init sa execute scriptul /etc/rc.d/rc.0 atunci cand va intra in nivelul de rulare "0" si sa astepte pana ce scriptul va termina tot ce are de facut.
A saptea intrare, cea de la linia 42, are urmatoarele calitati: Este identificata prin sirul de caractere "l6". Campul nivelelor de rulare este ocupat de catre "6", ceea ce inseamna ca intrarea se aplica nivelului de rulare "6". Campul actiunii este ocupat de catre "wait", iar procesul de catre scriptul /etc/rc.d/rc.6. Faptul ca "wait" ocupa campul actiune ii spune lui init sa execute scriptul /etc/rc.d/rc.6 atunci cand va intra in nivelul de rulare "6" si sa astepte pana ce scriptul va termina tot ce are de facut.
Urmatoarele 5 intrari -- de la linia 45 la linia 49 -- sint aproape identice, singurele lucruri care le deosebesc fiind campul care le identifica( oare de ce?:-) ) si penultimul parametru de executie al comenzii din campul proces. Toate au la campul nivelurilor de rulare caracterele "1235". Toate au in campul actiunii "respawn", iar la proces comanda "/sbin/agetty 38400 tty<x> linux", <x> diferind de la intrare la intrare. Faptul ca "respawn" ocupa campul actiune ii spune lui init sa regenereze procesul din campul proces, cand acesta isi termina executia. In cazul nostru, init va regenera o sesiune de identificare(engl. login prompt) in cazul in care aceasta se va sfarsi.
A treisprezecea intrare, cea de la linia 50, este are aceleasi proprietati ca si ultimele 5 intrari, doar ca intrarea este aplicata si nivelului de rulare "4", spre deosebire de precedentele.
Ultima intrare, cea de la linia 58, are urmatoarele calitati: Este identificata prin sirul de caractere "x1". Campul nivelurilor de rulare este ocupat de catre caracterul "4". Campul actiune este ocupat de catre "respawn", iar procesul de catre scriptul /etc/rc.d/rc.4. Faptul ca "respawn" ocupa campul actiune ii spune lui init sa reexecute scriptul /etc/rc.d/rc.4, cand acesta se va termina.
Lamuriri necesare pentru a continua. Mica erata a ceea ce a fost expus pana acum.
Probabil ca se observa niste neconcordante intre anumite lucruri ce-au fost descrise pana acum. De exemplu: Inainte sa depanam fisierul /etc/inittab, s-a spus ca valoarea din campul proces reprezinta un proces (ce, dupa cum am observat, poate fi o comanda sau un script) care va fi executat de catre init _l-a intrarea intr-un nivel de rulare_, dar noi am observat ca intr-unele intrari campul nivelurilor de rulare este gol, pe cand campul proces contine o valoare. De ce am spus asta? Pai, in primul rand, ca este mai usor de inteles un lucru partial adevarat, urmat de o lamurire, decat daca as intra in detalii de la bun inceput; si, in plus, explicatiile detaliate duc, dupa cum se pare, la exprimari tautologice ( ca sa fiu delicat :~) ), datorita unor termeni care nu se impac intr-o expresie/propozitie... Bun. Revenind.
Init, pe langa faptul ca este primul program executat, mai este si ultimul, -- asta in cazul in care procesul de oprire al calculatorului se deruleaza normal si corect. Ce ne spune acest lucru? Pai ne spune mai multe lucruri. Ne spune, de exemplu, ca pe parcursul timpului de executie al lui init, sistemul este 1. configurat 2. intretinut 3. deconfigurat. Vom urma in detaliu stagiile (1) si (3), dar hai sa spunem cateva lucruri despre fiecare in parte, chiar daca voi prelua anumite idei ce-au fost deja expuse.
- (1) Nucleul nu-l arunca pe init intr-un mediu complet configurat. De fapt, luat in mare, nu il lasa decat cu un sistem de fisiere radacina montat cu proprietatea de numai-citire, dupa care se retrage linistit in fundal, unde isi vede de treaba, printre altele punand la dispozitia programelor o suita de apeluri de sistem prin intermediu carora acestea comunica cu el. Pana ajungem noi sa ne autentificam, init are mult de munca. De fapt, prea il elogiez, caci el nu face toata treaba de unul singur, ci mai degraba o coordoneaza. Am observat ca el citeste fisierul /etc/inittab si ca de acolo afla, printre altele, ce scripturi sa execute pentru configurarea sistemului. Comenzile din acele scripturi, de fapt, pun in picioare sistemul, iar unul dintre rolurile lui init este sa ruleze aceste scripturi. Acest lucru ofera o mare flexibilitate administratorului sistemului, deoarece scripturile sint mai usor de inteles si de schimbat. Va imaginati ce-ar fi insemnat ca init sa faca toata treaba de unul singur, fara sa apeleze la BASH sau alt interpretor de comenzi? Ar fi insemnat ca init sa fie foarte complex, ar fi insemnat ca administratorul de sistem sa ii umble prin codul sursa, daca ar vrea sa schimbe ceva -- orice, dupa care sa-l recompileze s.a.m.d. Ca sa inchei scurta introducere a acestui stagiu, nu mai spun decat ca, in Slackware si derivatele sale, TOATE scripturile de care se foloseste init se afla in directorul /etc/rc.d/. Acest lucru nu este batut in cuie, putand foarte lejer sa schimbam asta prin modificarea campului proces al intrarilor din /etc/inittab, dar este o conventie utila si bine gandita, asa mai bine nu am schimba-o. De asemenea, vom urmari indeaproape fiecare script in parte.
- (2) Cum sta treaba cu intretinerea sistemului? Pai e lesne de imaginat ca, fiind primul program pornit si ruland _mereu_, chiar si dupa ce sistemul a fost configurat si noi deja ne bucuram de facilitile unui client de posta electronica, init nu sta degeaba. S-a specificat mai devreme, cand au fost enumerate unele dintre scopurile sale, ca se ocupa cu initializarea tuturor celorlalte procese, colectarea proceselor moarte s.a. Nu s-a specificat, in schimb, o proprietate specifica tuturor programelor ( a se citi proceselor ) unui sistem compatibil cu standardele ANSI/POSIX. Aceasta proprietate este aceea de a capta semnale. Probabil ca toti stim ce este un semnal, deoarece toti am folosit comanda kill. Stim ca programele pot fi programate(...) sa capteze anumite semnale, si sa interactioneze intr-un anume fel la primirea acestora. Asa face si init, dar spre deosebire de alte programe, ii poate fi specificat si cum sa reactioneze la primirea anumitor semnale. Cum ii specificam asta? Pai cum faceam si pana acum, cand voiam sa-i modelam comportamentul: folosindu-ne de fisierul /etc/inittab. Acum ajungem la acele neconcordante despre care vorbeam mai devreme, anume intrarile din fisierul /etc/inittab care contin nu contin un nivel de rulare, dar contin un proces.
36 ca::ctrlaltdel:/sbin/shutdown -t5 -r now
S-a specificat ca aceasta intrare are urmatoarea influenta asupra lui init: cand init primeste semnalul SIGINIT (care ii este trimis cand sint apasate, la consola, tastele CTRL+ALT+DELETE), acesta executa comanda /sbin/shutdown -t5 -r now. Faptul ca nu este specificat un nivel de rulare nu are vreo importanta, caci intrarea cu aceasta actiune se aplica oricarui 'nivel de rulare'( de fapt, daca init este pornit, nu conteaza daca sistemul este configurat sau ba, daca sintem intr-un nivel de rulare sau nu, va reactiona cum am spus mai devreme. ). Aceasta nu este singura actiune care ii spune lui init sa reactioneze cumva la primirea unui semnal. Distributia vine cu un fisier /etc/inittab care contine inca 2 intrari cu actiuni asemanatoare, anume powerfail si powerokwait, care reactioneaza la semnale primite de la sursa de alimentare neintreruptibila(engl. presc. UPS).
- (3) Despre acest stagiu nu s-a scris deloc pana acum. Pe scurt, deconfigurarea sistemului se face prin configurarea unor nivele de rulare pentru acest scop, nivele de rulare care sa execute anumite scripturi care sa faca, in mare parte, opusul scriptului de initializare + oprirea serviciilor specifice nivelului de rulare in care sintem. Aceste scripturi, in cazul de fata -- si in cazul unei distributii Slackware nemodificate --, sint /etc/rc.0 si /etc/rc.6, specifice nivelurilor de executie "0" si "6". Le vom urmari indeaproape.
In cele ce urmeaza, vom analiza stagiul (2), mai exact scripturile executate de catre init, folosindu-ne de fisierul /etc/inittab postat aici. Scripturile pe care le vom analiza sint cele care vin cu distributia, mai putin /etc/inittab, caruia i-au fost scoase 2 intrari care oricum n-au sa faca mare diferenta. Vom lua scripturile in ordinea executarii lor de catre init.
/etc/rc.S
Are urmatoarele calitati:
- 1. Este primul script executat de catre init.
- 2. Este rulat inainte de executarea oricarui script specific vreunui nivel de rulare.
Scriptul este voluminos. In cele ce urmeaza, continutul sau va fi postat in varianta originala. Nu voi scoate comentariile, acestea fiind de ajutor daca stiti ceva 'engleza tehnica'; daca nu stiti, sau nu intelegeti, oricum voi repeta (si adauga) explicatii in limba romana, pentru fiecare instructiune sau bloc de instructiuni.
Observatie: Am pornit de la bun inceput de la premiza ca aveti ceva cunostinte legate de interpretorul de comenzi BASH si despre mediul GNU/Linux (comenzi elementare, machetarea fisierelor s.a.m.d.), intr-atat incat sa intelegeti o buna parte din toate cele ce-ar urma, chiar daca doar semantic. Daca nu aveti experienta cu cele mai sus enumerate, puteti profita de rigurozitatea cu care se va incerca explicarea scripturilor si, impreuna cu tutorialele/indrumarele specificate la finalul ghidului, sa analizati mecanismele acestea folosite in viata reala.
err@coliba:~$ cat -n /etc/rc.d/rc.S 1 #!/bin/sh 2 # 3 # /etc/rc.d/rc.S: System initialization script. 4 # 5 # Mostly written by: Patrick J. Volkerding, <volkerdi@slackware.com> 6 # 7 8 PATH=/sbin:/usr/sbin:/bin:/usr/bin 9 10 # Mount /proc right away: 11 /sbin/mount -v proc /proc -n -t proc 12 13 # If 'nohotplug' was given at boot, or rc.hotplug has been turned off 14 # (and a 2.4.x kernel is running), then shut off hotplugging in the 15 # kernel now. Realize that if you turn off hotplugging support that 16 # you will have to load all the kernel modules that you need yourself 17 # (possibly in /etc/rc.d/rc.modules, which does not promise to list 18 # all of them), and make any additional device nodes that you need in 19 # the /dev directory. 20 if [ -w /proc/sys/kernel/hotplug ]; then 21 # Kernel command line option 'nohotplug' given, so we will shut off 22 # hotplugging even if it is not a good idea. Sometimes it *is* a 23 # good idea, especially when you're trying to figure out which 24 # kernel module is crashing the machine and needs to be added to 25 # your /etc/modprobe.d/blacklist (2.6+ kernels) and/or your 26 # /etc/hotplug/blacklist (2.4.x kernels). 27 if grep -wq nohotplug /proc/cmdline ; then 28 echo "/dev/null" > /proc/sys/kernel/hotplug 29 elif [ ! -x /etc/rc.d/rc.hotplug ]; then 30 # Ignore /etc/rc.d/rc.hotplug on kernels newer than 2.4.x: 31 if [ ! "$(uname -r | cut -f 1,2 -d .)" = "2.4" ]; then 32 # We must be running a 2.4.x kernel, so turn off hotplug: 33 echo "/dev/null" > /proc/sys/kernel/hotplug 34 fi 35 fi 36 fi 37 38 # Start devfsd if necessary. On newer kernels, udev should be used instead. 39 if [ -x /etc/rc.d/rc.devfsd ]; then 40 /etc/rc.d/rc.devfsd start 41 fi 42 43 # Mount sysfs next, if the kernel supports it: 44 if [ -d /sys ]; then 45 if cat /proc/filesystems | grep -wq sysfs ; then 46 if ! cat /proc/mounts | grep -wq sysfs ; then 47 /sbin/mount -v sysfs /sys -n -t sysfs 48 fi 49 fi 50 fi 51 52 # Enable swapping: 53 /sbin/swapon -a 54 55 # Test to see if the root partition is read-only, like it ought to be. 56 READWRITE=no 57 if touch /fsrwtestfile 2>/dev/null; then 58 rm -f /fsrwtestfile 59 READWRITE=yes 60 else 61 echo "Testing root filesystem status: read-only filesystem" 62 fi 63 64 # See if a forced filesystem check was requested at shutdown: 65 if [ -r /etc/forcefsck ]; then 66 FORCEFSCK="-f" 67 fi 68 69 # Check the root filesystem: 70 if [ ! $READWRITE = yes ]; then 71 RETVAL=0 72 if [ ! -r /etc/fastboot ]; then 73 echo "Checking root filesystem:" 74 /sbin/fsck $FORCEFSCK -C -a / 75 RETVAL=$? 76 fi 77 # An error code of 2 or higher will require a reboot. 78 if [ $RETVAL -ge 2 ]; then 79 # An error code equal to or greater than 4 means that some errors 80 # could not be corrected. This requires manual attention, so we 81 # offer a chance to try to fix the problem in single-user mode: 82 if [ $RETVAL -ge 4 ]; then 83 echo 84 echo "***********************************************************" 85 echo "*** An error occurred during the root filesystem check. ***" 86 echo "*** You will now be given a chance to log into the ***" 87 echo "*** system in single-user mode to fix the problem. ***" 88 echo "*** ***" 89 echo "*** If you are using the ext2 filesystem, running ***" 90 echo "*** 'e2fsck -v -y <partition>' might help. ***" 91 echo "***********************************************************" 92 echo 93 echo "Once you exit the single-user shell, the system will reboot." 94 echo 95 PS1="(Repair filesystem) \#"; export PS1 96 sulogin 97 else # With an error code of 2 or 3, reboot the machine automatically: 98 echo 99 echo "***********************************" 100 echo "*** The filesystem was changed. ***" 101 echo "*** The system will now reboot. ***" 102 echo "***********************************" 103 echo 104 fi 105 echo "Unmounting file systems." 106 /sbin/umount -a -r 107 /sbin/mount -n -o remount,ro / 108 echo "Rebooting system." 109 sleep 2 110 reboot -f 111 fi 112 # Remount the root filesystem in read-write mode 113 echo "Remounting root device with read-write enabled." 114 /sbin/mount -w -v -n -o remount / 115 if [ $? -gt 0 ] ; then 116 echo 117 echo "Attempt to remount root device as read-write failed! This is going to" 118 echo "cause serious problems." 119 echo 120 echo "If you're using the UMSDOS filesystem, you **MUST** mount the root partition" 121 echo "read-write! You can make sure the root filesystem is getting mounted " 122 echo "read-write with the 'rw' flag to Loadlin:" 123 echo 124 echo "loadlin vmlinuz root=/dev/hda1 rw (replace /dev/hda1 with your root device)" 125 echo 126 echo "Normal bootdisks can be made to mount a system read-write with the rdev command:" 127 echo 128 echo "rdev -R /dev/fd0 0" 129 echo 130 echo "You can also get into your system by using a boot disk with a command like this" 131 echo "on the LILO prompt line: (change the root partition name as needed)" 132 echo 133 echo "LILO: mount root=/dev/hda1 rw" 134 echo 135 echo "Please press ENTER to continue, then reboot and use one of the above methods to" 136 echo -n "get into your machine and start looking for the problem. " 137 read junk; 138 fi 139 else 140 echo "Testing root filesystem status: read-write filesystem" 141 if cat /etc/fstab | grep ' / ' | grep -wq umsdos ; then 142 ROOTTYPE="umsdos" 143 fi 144 if [ ! "$ROOTTYPE" = "umsdos" ]; then # no warn for UMSDOS 145 echo 146 echo "*** ERROR: Root partition has already been mounted read-write. Cannot check!" 147 echo 148 echo "For filesystem checking to work properly, your system must initially mount" 149 echo "the root partition as read only. Please modify your kernel with 'rdev' so that" 150 echo "it does this. If you're booting with LILO, add a line:" 151 echo 152 echo " read-only" 153 echo 154 echo "to the Linux section in your /etc/lilo.conf and type 'lilo' to reinstall it." 155 echo 156 echo "If you boot from a kernel on a floppy disk, put it in the drive and type:" 157 echo " rdev -R /dev/fd0 1" 158 echo 159 echo "If you boot from a bootdisk, or with Loadlin, you can add the 'ro' flag." 160 echo 161 echo "This will fix the problem *AND* eliminate this annoying message. :^)" 162 echo 163 echo -n "Press ENTER to continue. " 164 read junk; 165 fi 166 fi # Done checking root filesystem 167 168 # Any /etc/mtab that exists here is old, so we delete it to start over: 169 /bin/rm -f /etc/mtab* 170 # Remounting the / partition will initialize the new /etc/mtab: 171 /sbin/mount -w -o remount / 172 173 # Fix /etc/mtab to list sys and proc if they were not yet entered in 174 # /etc/mtab because / was still mounted read-only: 175 if [ -d /proc/sys ]; then 176 /sbin/mount -f proc /proc -t proc 177 fi 178 if [ -d /sys/bus ]; then 179 /sbin/mount -f sysfs /sys -t sysfs 180 fi 181 182 # Initialize udev to manage /dev entries and hotplugging for 2.6.x kernels. 183 # You may turn off udev by making the /etc/rc.d/rc.udev file non-executable, 184 # but in the 2.6.x+ kernels udev has taken over the job of hotplug (finding 185 # hardware and loading the kernel modules for it, as well as creating device 186 # nodes in /dev). Realize that if you turn off udev that you will have to 187 # load all the kernel modules that you need yourself (possibly in 188 # /etc/rc.d/rc.modules, which does not promise to list all of them), and 189 # make any additional device nodes that you need in the /dev directory. 190 # Even USB and IEEE1394 devices will need to have the modules loaded by 191 # hand if udev is not used with a 2.6 kernel. So use it. :-) 192 if cat /proc/mounts | grep -wq sysfs && cat /proc/filesystems | grep -wq tmpfs ; then 193 if ! grep -wq nohotplug /proc/cmdline ; then 194 if [ -x /etc/rc.d/rc.udev ]; then 195 /bin/sh /etc/rc.d/rc.udev start 196 /bin/sh /lib/udev/udev.count_events.sh 197 fi 198 fi 199 fi 200 201 # Set the system time from the hardware clock using hwclock --hctosys. 202 if [ -x /sbin/hwclock ]; then 203 # Check for a broken motherboard RTC clock (where ioports for rtc are 204 # unknown) to prevent hwclock causing a hang: 205 if ! grep -q -w rtc /proc/ioports ; then 206 CLOCK_OPT="--directisa" 207 fi 208 if grep -wq "^UTC" /etc/hardwareclock ; then 209 echo "Setting system time from the hardware clock (UTC)." 210 /sbin/hwclock $CLOCK_OPT --utc --hctosys 211 else 212 echo "Setting system time from the hardware clock (localtime)." 213 /sbin/hwclock $CLOCK_OPT --localtime --hctosys 214 fi 215 fi 216 217 # Configure ISA Plug-and-Play devices: 218 if [ -r /etc/isapnp.conf ]; then 219 if [ -x /sbin/isapnp ]; then 220 /sbin/isapnp /etc/isapnp.conf 221 fi 222 fi 223 224 # This loads any kernel modules that are needed. These might be required to 225 # use your ethernet card, sound card, or other optional hardware. 226 # Priority is given first to a script named "rc.modules.local", then 227 # to "rc.modules-$FULL_KERNEL_VERSION", and finally to the plain "rc.modules". 228 # Note that if /etc/rc.d/rc.modules.local is found, then that will be the ONLY 229 # rc.modules script the machine will run, so make sure it has everything in 230 # it that you need. 231 if [ -x /etc/rc.d/rc.modules.local -a -r /proc/modules ]; then 232 echo "Running /etc/rc.d/rc.modules.local:" 233 /bin/sh /etc/rc.d/rc.modules.local 234 elif [ -x /etc/rc.d/rc.modules-$(uname -r) -a -r /proc/modules ]; then 235 echo "Running /etc/rc.d/rc.modules-$(uname -r):" 236 . /etc/rc.d/rc.modules-$(uname -r) 237 elif [ -x /etc/rc.d/rc.modules -a -r /proc/modules -a -L /etc/rc.d/rc.modules ]; then 238 echo "Running /etc/rc.d/rc.modules -> $(readlink /etc/rc.d/rc.modules):" 239 . /etc/rc.d/rc.modules 240 elif [ -x /etc/rc.d/rc.modules -a -r /proc/modules ]; then 241 echo "Running /etc/rc.d/rc.modules:" 242 . /etc/rc.d/rc.modules 243 fi 244 245 # Configure runtime kernel parameters: 246 if [ -x /sbin/sysctl -a -r /etc/sysctl.conf ]; then 247 /sbin/sysctl -e -p /etc/sysctl.conf 248 fi 249 250 # Initialize the Logical Volume Manager. 251 # This won't start unless we find /etc/lvmtab (LVM1) or 252 # /etc/lvm/backup/ (LVM2). This is created by /sbin/vgscan, so to 253 # use LVM you must run /sbin/vgscan yourself the first time (and 254 # create some VGs and LVs). 255 if [ -r /etc/lvmtab -o -d /etc/lvm/backup ]; then 256 echo "Initializing LVM (Logical Volume Manager):" 257 # Check for device-mapper support. 258 if ! cat /proc/devices | grep -wq device-mapper ; then 259 # If device-mapper exists as a module, try to load it. 260 if [ -r /lib/modules/$(/bin/uname -r)/kernel/drivers/md/dm-mod.ko ]; then 261 insmod /lib/modules/$(/bin/uname -r)/kernel/drivers/md/dm-mod.ko 262 fi 263 fi 264 # Scan for new volume groups: 265 KERNEL_VERSION=$(/bin/uname -r | /bin/cut -d . -f 1,2) 266 if [ "$KERNEL_VERSION" == "2.4" ]; then 267 /sbin/vgscan 2> /dev/null 268 else 269 /sbin/vgscan --ignorelockingfailure 2> /dev/null 270 fi 271 if [ $? = 0 ]; then 272 # Make volume groups available to the kernel. 273 # This should also make logical volumes available. 274 if [ "$KERNEL_VERSION" == "2.4" ]; then 275 /sbin/vgchange -ay 276 else 277 /sbin/vgchange -ay --ignorelockingfailure 278 fi 279 # Enable swapping again in case any LVs are used for swap. Ignore previous error. :-) 280 /sbin/swapon -a 281 fi 282 fi 283 284 # Check all the non-root filesystems: 285 if [ ! -r /etc/fastboot ]; then 286 echo "Checking non-root filesystems:" 287 /sbin/fsck $FORCEFSCK -C -R -A -a 288 fi 289 290 # Mount usbfs if we're not using hotplug: 291 if grep -wq usbfs /proc/filesystems; then 292 if /bin/grep -wq nohotplug /proc/cmdline || /bin/test ! -x /etc/rc.d/rc.hotplug ; then 293 if ! cat /proc/mounts | grep -wq usbfs ; then 294 /sbin/mount -v usbfs /proc/bus/usb -t usbfs 295 fi 296 fi 297 fi 298 299 # Mount non-root file systems in fstab, but not NFS or SMB 300 # because TCP/IP is not yet configured, and not proc or sysfs 301 # because those have already been mounted. Also check that 302 # devpts is not already mounted before attempting to mount 303 # it. With 2.4.x kernels devpts is mounted from an fstab 304 # entry while with a 2.6.x or newer kernel udev mounts it. 305 # We also need to wait a little bit to let USB and other 306 # hotplugged devices settle (sorry to slow down the boot): 307 echo "Mounting non-root local filesystems:" 308 sleep 3 309 if /bin/grep -wq devpts /proc/mounts ; then 310 /sbin/mount -a -v -t nonfs,nosmbfs,nocifs,noproc,nosysfs,nodevpts 311 else 312 /sbin/mount -a -v -t nonfs,nosmbfs,nocifs,noproc,nosysfs 313 fi 314 315 # Enable swapping again. This is needed in case a swapfile is used, 316 # as it can't be enabled until the filesystem it resides on has been 317 # mounted read-write. 318 /sbin/swapon -a 319 320 # Clean up some temporary files: 321 ( cd /var/log/setup/tmp && rm -rf * ) 322 /bin/rm -f /var/run/utmp /var/run/*pid /etc/nologin /var/run/lpd* \ 323 /var/run/ppp* /etc/dhcpc/*.pid /etc/forcefsck /etc/fastboot \ 324 /var/state/saslauthd/saslauthd.pid 325 326 # Create /tmp/{.ICE-unix,.X11-unix} if they are not present: 327 if [ ! -e /tmp/.ICE-unix ]; then 328 mkdir -p /tmp/.ICE-unix 329 chmod 1777 /tmp/.ICE-unix 330 fi 331 if [ ! -e /tmp/.X11-unix ]; then 332 mkdir -p /tmp/.X11-unix 333 chmod 1777 /tmp/.X11-unix 334 fi 335 336 # Attempt to umount and remove any leftover /initrd: 337 if [ -d /initrd ]; then 338 umount /initrd/proc 2> /dev/null 339 /sbin/umount /initrd 2> /dev/null 340 rmdir /initrd 2> /dev/null 341 blockdev --flushbufs /dev/ram0 2> /dev/null 342 fi 343 344 # Create a fresh utmp file: 345 touch /var/run/utmp 346 chown root:utmp /var/run/utmp 347 chmod 664 /var/run/utmp 348 349 if [ "$ROOTTYPE" = "umsdos" ]; then # we need to update any files added in DOS: 350 echo "Synchronizing UMSDOS directory structure:" 351 echo " /sbin/umssync -r99 -v- /" 352 /sbin/umssync -r99 -v- / 353 fi 354 355 # Setup the /etc/motd to reflect the current kernel level: 356 # THIS WIPES ANY CHANGES YOU MAKE TO /ETC/MOTD WITH EACH BOOT. 357 # COMMENT THIS OUT IF YOU WANT TO MAKE A CUSTOM VERSION. 358 echo "$(/bin/uname -sr)." > /etc/motd 359 360 # If there are SystemV init scripts for this runlevel, run them. 361 if [ -x /etc/rc.d/rc.sysvinit ]; then 362 . /etc/rc.d/rc.sysvinit 363 fi 364 365 # Run serial port setup script: 366 # CAREFUL! This can make some systems hang if the rc.serial script isn't 367 # set up correctly. If this happens, you may have to edit the file from a 368 # boot disk, and/or set it as non-executable: 369 if [ -x /etc/rc.d/rc.serial ]; then 370 sh /etc/rc.d/rc.serial start 371 fi 372 373 # Carry an entropy pool between reboots to improve randomness. 374 if [ -f /etc/random-seed ]; then 375 echo "Using /etc/random-seed to initialize /dev/urandom." 376 cat /etc/random-seed > /dev/urandom 377 fi 378 # Use the pool size from /proc, or 512 bytes: 379 if [ -r /proc/sys/kernel/random/poolsize ]; then 380 dd if=/dev/urandom of=/etc/random-seed count=1 bs=$(cat /proc/sys/kernel/random/poolsize) 2> /dev/null 381 else 382 dd if=/dev/urandom of=/etc/random-seed count=1 bs=512 2> /dev/null 383 fi 384 chmod 600 /etc/random-seed 385
Preferabil sa deschideti de doua ori pagina, ca sa va fie mai comoda orientarea.
<linie/i>: <explicatie>
8: Este setata variabila de mediu PATH. PATH are urmatoarea forma: director:director:director[:director...] si urmatoarea calitate: Ii spune interpretorului in ce directoare sa se uite pentru fisierele executabile care nu au calea absoluta specificata.
11: Este montat sistemul de fisiere virtual procfs. Folosindu-ne acest sistem de fisiere, vom putea afla informatii ce reflecta starea curenta a nucleului. Vom vedea imediat despre ce este vorba.
20-36: Se verifica daca fisierul /proc/sys/kernel/hotplug exista si poate fi modificat ( [ -w ] ). Existenta acestui fisier inseamna ca nucleul are suport pentru subsistemul hotplug(traducere?), un sistem de configurare dinamica a componentelor hard. Vom intra in detalii mai tarziu.
Dupa aceasta, in cazul in care nucleul are suport pentru hotplug, se verifica daca nucleului i-a fost trimis parametrul de executie "nohotplug". Aceasta verificare are loc prin inspectarea continutului fisierului /proc/cmdline, fisier ce contine toti parametrii trimisi nucleului de catre programul de incarcare. In cazul in care nucleului i-a fost trimis parametrul de executie "nohotplug", atunci continutul fisierului /proc/sys/kernel/hotplug este schimbat in "/dev/null". Continutul fisierului /proc/sys/kernel/hotplug reprezinta calea catre programul care va fi instintat de catre nucleu, cand va avea loc un eveniment(in cazul acesta, cand o componenta hard va fi cuplata). Prin schimbarea continutului fisierului /proc/sys/kernel/hotplug in "/dev/null", sistemul hotplug este dezactivat, deoarece orice instintare a nucleului cu privire la evenimente hotplug va fi iignorata.
Daca nucleului n-a fost pornit cu parametrul de executie "nohotplug", se va verifica daca scriptul /etc/rc.d/rc.hotplug este neexecutabil [ ! -x ], caz in care se verifica daca nucleul NU face parte din bransa 2.4.x, caz in care se dezactiveaza sistemul hotplug, schimbandu-se continutul fisierului /proc/sys/kernel/hotplug in "/dev/null". Scriptul /etc/rc.d/rc.hotplug porneste sistemul hotplug, asa ca mai devreme a fost verificat pentru a vedea daca este activat de catre administrator. Daca acesta este activat, adica este executabil, va fi rulat de catre nivelele de rulare care vor avea suport pentru hotplug. Vom analiza scriptul /etc/rc.d/rc.hotplug atunci cand ne vom intalni cu executarea acestuia.
39-41: Se verifica daca scriptul /etc/rc.d/rc.devfsd este prezent si executabil, caz in care scriptul este executat. Scriptul porneste si configureaza, prin intermediul lui defvsd, fisierele /dev. Aceste intrari probabil ca inca mai exista in /etc/rc.S din motive istorice, caci devfs a fost scos din Slackware inca de la versiunea 10.0. Daca doriti sa scadeti cu cateva milisecunde din timpul de initializare, puteti sa stergeti intrarile.
44-50: Se verifica daca exista directorul /sys [ -d ], caz in care se verifica daca nucleul suporta sistemul de fisiere virtual sysfs. Aceasta verificare se face prin inspectarea fisierului /proc/filesystems, care contine o lista cu sistemele de fisere suportate de nucleu. Daca exista, atunci este verificat fisierul /proc/mounts, pentru a vedea daca sistemul de fisiere sysfs nu este deja montat. /proc/mounts contine o lista cu sistemele de fisiere deja montate. Daca sysfs nu este deja montat, este montat.(...)
Sysfs este un sistem virtual de fisiere, ca si procfs, care ofera informatii despre driverele nucleului. Nucleul din bransa 2.4.x nu are suport pentru acest sistem de fisiere virtual, asa ca daca nu o sa treceti pe 2.6.x, puteti sa stergeti aceste intrari, de doriti cateva milisecunde scazute din timpul de initializare.
56-62: Variabila READWRITE este initializata cu valoarea "no", ce reflecta starea in care ar trebui sa fie in mod normal montat sistemul de fisiere radacina de catre nucleu, adica cu optiunea de numai-citire. Prin incercarea crearii unui fisier pe sistemul de fisiere radacina, se verifica daca se poate scrie pe acesta, caz in care fisierul test este sters, iar valoarea variabilei READWRITE este schimbata in "yes", cat sa reflecte adevarata stare a sistemului de fisiere radacina.
65-67: Se verifica daca exista fisierul citabil /etc/forcefsck, caz in care este initializata variabila FORCEFSK cu valoarea "-f". Aceasta variabila va fi folosita ca parametru optional pentru comanda fsck.
70-166: Se verifica daca sistemul de fisiere radacina nu este montat cu optiunea numai-citire, caz in care au loc urmatorii pasi:
- Variabila RETVAL este initializata cu valoarea 0.
- Se verifica daca nu exista fisierul citabil /etc/fastboot, caz in care se verifica integritatea sistemului de fisiere radacina prin intermediul comenzii fsck.
- RETVAL isi schimba continutul in valoarea returnata de catre comanda fsck.
- Se verifica daca valoarea lui RETVAL este mai mare sau egala cu 2, caz in care sa verifica daca valoarea lui RETVAL este mai mare sau egala cu 4, caz in care sintem avertizati de anumite erori ce-au avut loc pe parcursul inspectarii lui fsck si sintem aruncati in modul utilizator-unic, pentru a depana problemele aparute. Altfel, daca valoarea lui RETVAL este intre 2 si 4, sint demontate sistemele de fisiere, iar calculatorul este repornit.
- Daca valoarea lui RETVAL este 0 sau 1, atunci se incearca remontarea sistemului de fisiere radacina cu optiunea de citire-scriere, prin intermediul comenzii mount.
- Valoarea returnata de catre comanda mount este verificata daca este mai mare decat 0, caz in care sintem intampinati cu niste erori si indemnati sa repornim calculatorul, folosindu-ne de sfaturile din avertizari. In schimb, daca valoarea returnata de mount este 0 [...]
169-171: Este sters fisierul /etc/mtab, iar sistemul de fisiere radacina si sistemele virtuale de fisiere procfs si sysfs sint remontate. Acesti pasi sint facuti pentru ca fisierul /etc/mtab este vechi, de la ultima initializare a sistemului, si trebuie refacut. Fisierul /etc/mtab contine o lista cu sistemele de fisiere montate montate in acest moment.
192-199: Se incearca pornirea lui udev, care este un inlocuitor al lui hotplug, pentru nucleele din bransa 2.6.x. Intai se verifica daca este montat sistemul virtual de fisiere sysfs si daca nucleul suporta sistemul virtual de fisiere tmpfs, caz in care se verifica daca nucleul n-a fost pornit cu parametrul de executie "nohotplug", caz in care se verifica daca scriptul /etc/rc.d/rc.udev exista si este executabil, caz in care acest script este executat impreuna cu /lib/udev/udev.count_events.sh.
202-215: Este setata ora sistemului, folosindu-se de comanda hwclock cu parametrul sau de executie --hctosys. Intai se verifica daca exista executabilul /sbin/hwclock. Daca exista, se verifica intrarile din /proc/ioports (fisier ce contina o lista cu conectorii de intrare-iesire activi) pentru rtc ( real time clock — ceas in timp real, un ceas care continua sa functioneze chiar si atunci cand calculatorul este oprit ). Daca se gaseste o asemenea intrare, variabila CLOCK_OPT este initializata cu valoarea "--directisa". Se verifica daca fisierul /etc/hardwareclock contine o intrare care incepe cu sirul de caractere "UTC", caz in care se executa comanta /hwclock, insotita de parametrii $CLOCK_OPT, --utc si --hctosys, altfel se executa aceeasi comanda, dar in loc de --utc se foloseste --localtime.[erm, detaliere..]
218-22: Se verifica daca fisierul /etc/isapnp.conf si este modificabil, caz in se verifica existenta fisierului executabil /sbin/isapnp, caz in care comanda /sbin/isapnp este rulata cu parametrul de executie /etc/isapnp.conf. Programul isapnp face parte din suita de utilitare isapnptools, care se ocupa cu configurarea dispozitivelor ISA autoconfigurabile(engl. ISA Plug and Play devices). Daca n-aveti asemenea dispozitive, puteti sa stergeti intrarile, de doriti cateva milisecunde in plus la initializare. Chiar mai mult, de la nucleele din bransa 2.4. Ba mai mult, daca folositi nuclee din bransa 2.6, ati putea sterge aceste intrari chiar daca aveti dispozitive ISA autoconfigurabile, deoarece nucleul nu va mai fi nevoit sa comunice cu isapnp, driverele(?) dispozitivelor facandu-si suficient de bine treaba.
231-243: Se va verifica existenta unor scripturi executabile prin intermediul carora vor fi incarcate anumite module ale nucleului. Pasii sint urmatorii: Se verifica existenta scriptului executabil /etc/rc.d/rc.modules.local, cat si existenta fisierului modificabil /proc/modules (care contine o lista cu modulele incarcate in acest moment), iar daca acestea exista, se scrie pe ecran ca scriptul va fi executat, dupa care acesta este executat.
Daca acestea nu exista, se verifica existenta fisierului executabil /etc/rc.d/rc.modules-(versiune nucleu), cat si existenta fisierului modificabil /proc/modules, iar daca acestea exista, se scrie pe ecran ca scriptul va fi executat, dupa care acesta este executat.
Daca nici de data aceasta scriptul sau /proc/modules nu este gasit, se verifica existenta scriptului executabil /etc/rc.d, existenta fisierului modificabil /proc/modules, cat si daca scriptul /etc/rc.d este un link(?) simbolic [ -L ], caz in care se scrie pe ecran ca scriptul va fi executat (se afiseaza si catre ce indica linkul simbolic, prin intermediul comenzii readlink), iar scriptul este executat.
Daca nici acum nu s-au validat conditiile, atunci se repeta ultimii pasi, mai putin cu verificarea scriptului pentru calitatea de link simbolic.
Dupa atatea 'daca'-uri, se trage concluzia ca la prima validare a unui script, acesta este executat, restul intrarilor fiind ignorate. Asa ca este indicat sa ne asiguram ca specificam intr-un singur script toate modulele ce ar trebui incarcate, iar daca tot facem acest lucru, putem sa stergem restul intrarilor, daca dorim cateva de milisecunde scazute din perioada deinitializare.
246-248: Se verifica existenta fisierului executabil /sbin/sysctl si a fisierului modificabil, iar daca acestea exista, este rulata comanda /sbin/sysctl. Prin intermediul lui /sbin/sysctl, putem sa setam anumiti parametrii ai nucleului in timp ce acesta ruleaza. Daca nu avem de gand sa-i trimitem niste parametrii de rulare nucleului pe parcursul procesului de initializare, putem sa stergem aceste intrari, daca dorim cateva milisecunde scazute din perioada de initializare. [...]
255-282: Aceste intrari pornesc si configureaza LVM. LVM este unul din visurile devenite realitate ale administratorului de sistem sau al utilizatorului care s-a saturat sa gandeasca un sistem optim de partitionare a dispozitivelor de stocare! Este un serviciu foarte folositor, pus la dispozitie de nucleu, prin intermediul caruia partitiile fizice sint combinate in 'partitii virtuale'(care sint denumite volume logice in nomenclatura LVM'ului), in asa fel se pot realiza anumite operatii cu partiile care altfel ar fi imposibil fara stergerea unitatii de stocare si repartitionarea sa. De exemplu, in cazul in care s-a umplut o partitie, aceasta poate fi marita prin 'imprumutarea' spatiului de pe alta partitie; sau daca se adauga un o noua unitate de disk, spatiul acesteia poate fi alocat unei partitii sau unui grup de partitii deja existenta pe discul actual. Revenind, sa urmarim cum are loc initializarea LVM'ului:
Intai se verifica daca exista fisierul modificabil /etc/lvm1(folosit de versiuna 1 a LVM) sau directorul /etc/lvm/backup(folosit de versiunea 2 a LVM). Faptul ca aceste fisiere nu exista acum nu inseamna neaparat ca nu avem suport pentru LVM, ci doar ca n-au fost create. Ele trebuiesc create manual, iar pentru acest lucru este folosita comanda vgscan(8). Spun "ele", dar de fapt nu se creaza decat 1 singur fisier/director, in functie de versiunea LVM. Bun, in caz de au fost create, se continua procesul.
Ni se specifica faptul ca LVM va fi pornit. Se verifica daca fisierul /proc/devices NU contine o intrare "device-mapper", caz in care se verifica existenta modului "dm-mod.ko", iar, daca acesta exista, este incarcat. Fisierul /proc/devices contine o lista cu driverele(?) dispozitivelor care sint momentan incarcate in nucleu. "device-mapper" este o componenta noua a nucleelor din bransa 2.6.x, dar poate fi folosit si cu nuclee din bransa 2.4.x, daca acestea sint corectate(engl. patched), asa ca intrarea poate fi stearsa, daca nu se va folosi un nucleu ce suporta aceasta facilitate.
Dupa ce este incarcat modului "dm-mod.ko", variabila KERNEL_VERSION este initializata cu valoarea primelor 2 numere din versiunea actuala a nucleului. Se verifica daca valoarea variabilei KERNEL_VERSION este egala cu "2.4", caz in care se executa comanda /sbin/vgscan, iar erorile acestei comenzi sint redirectionate catre /dev/null (2>). Daca valoarea variabilei KERNEL_VERSION nu este "2.4", atunci se executa comanta /sbin/vgscan --ignorelockingfailure, iar erorile acestei comenzi sint redirectionate catre /dev/null.
Se verifica daca valoarea returnata de catre comanda vgscan este egala cu zero (0 este returnat in caz ca totul s-a efectuat cu succes), caz in care se verifica inca o data daca versiunea nucleului este din bransa 2.4, caz in care se executa comanda /sbin/vgchange -ay. Daca nucleul nu face parte din bransa 2.4, se executa comanda /sbin/vgchange -ay --ignorelockingfailure. Comanda /sbin/vgchange -ay activeaza toate grupele volum din sistem. De mentionat ca, daca se verifica paginile manual cat si codul sursa al programelor carora le este trimis parametrul --ignorelockingfailure, se va observa ca acestea n-au suport pentru o optiune cu acest nume, asa ca folosirea lui este redundanta, ceea ce inseamna ca se pot scoate verificarile versiunii nucleului care conditioneaza folosirea acestor comenzi. Desigur, daca nu configuram nucleul cu suport pentru LVM, putem sa scoatem toate aceste intrari, daca dorim cateva milisecunde scazute din timpul de initializare.
321-324: Se sterg niste fisiere (posibil) lasate in de la repornirea calculatorului. Directorul /var/log/setup/tmp este folosit de pkgtool(cu precadere de catre installpkg). Fisierul /var/run/utmp contine informatii despre cine este autentificat in momentul acesta (este folosit de programe ca login). Fisierele din /var/run care se termina cu *pid sint, conform FHS, fisiere identificatoare ale proceselor (engl. presc. PID files), care contin PID'ul unor servicii ce ruleaza acum. Fisierul /etc/nologin, daca ar exista, i-ar spune lui login sa permita doar superutilizatorului sa se autentifice, asa ca daca doriti aceasta optiune stergeti intrarea. Fisierele /var/run/ppp* contin diverse informatii despre serviciile care pun la dispozitie conexiunea ppp. La fel si cu fisierele /etc/dhcpc/*.pid, doar ca ofera informatii despre serviciile dhcp. Fisierul /etc/forcefsck, dupa cum am observat, daca este existent, este folosit ca parametru "-f" de executare pentru fsck. Fisierul /etc/fastboot, daca exista, specifica lui /etc/rc.S sa treaca peste verificarea integritatii discului. Fisierul /var/state/saslauthd/saslauthd.pid contine informatii cu privire la PID'ul demonului salsd, daca acesta ruleaza. Pot fi sterse intrarile care se stiu ca nu vor fi folosite.
327-334: Se verifica daca NU exista directoarele /tmp/.ICE-unix si /tmp.X11-unix, caz in care acestea sint create. Aceste directoare contin informatii cu privire la serverul/sesiunile X actual/e.
[...]