System Bootstrap

Bootstrap

Tour guidato dalla pressione del tasto di accensione del PC fino al primo processo applicativo del sistema operativo Linux.

Contents

Introduzione

Il processo di avvio di un pc viene definito 'Bootstrap' che in senso letterale significa : 'tirandosi su con le cinghie dei propri stivali' ma in ambito informatico indica l'avvio di un computer. Durante il bootstrap vengono eseguite numerose operazioni ed eseguiti dei file di configurazione che rendono il processo potenzialmente vulnerabile e allo stesso tempo delicato; errori nei file di configurazione, componenti mancanti o corrotti e filesystem danneggiati possono compromettere l'avvio del computer. Quando il computer viene avviato viene caricato del codice residente in una memoria ROM che tenta a sua volta di stabilire come caricare il componente fondamentale del sistema operativo : il kernel. Per fare questo le operazioni sono numerose ma con il caricamento del kernel non si completa la fase di bootstrap in quanto il sistema ancora non è pronto per poter essere utilizzato. Prima della comparsa del login devono accadere molte cose : i filesystem devono essere controllati e montati; devono essere avviati i demoni del sistema che vengono controllati da una serie di script gestiti in successione dal padre di tutti i processi : INIT. Gli script prendono il nome di RC che sta per Run Command, una reminescenza del sistema operativo CTSS  utilizzato negli anni 60. Il documento tenta di esplorare il processo di avvio di Linux dalla pressione del tasto di accensione/reset fino al primo processo applicativo; il boot di un pc si è semplificato con il passare del tempo ma non per questo significa che sia semplice.

Overview

Quando un sistema viene acceso per la prima volta o viene effettuato il reset, il processore esegue del codice da una posizione ben conosciuta. In un PC questa locazione è nel Basic Input Output System (BIOS) che è memorizzato in una memoria flash montata sulla motherboard. La Central Processing Unit (CPU) è il componente che invoca il BIOS da un indirizzo di memoria preciso; il Bios determina quali dispositivi (devices) sono candidati per il boot. Quando il device viene individuato il primo stadio (Stage 1) del boot loader viene caricato in RAM ed eseguito. Questo boot loader è inferiore ai 512 bytes e il suo compito è quello di caricare il secondo stadio (Stage 2) del boot loader. Quando anche lo Stage 2 è stato caricato in RAM ed eseguito, una schermata di avvio viene tipicamente visualizzata e, sia Linux che un disco RAM iniziale (initial RAM disk o initrd) - come root file system temporaneo - vengono caricati in memoria. Quando l'immagine del kernel viene caricata lo stage 2 del boot loader gli lascia il controllo in modo che possa essere decompressa e inizializzata. A questo punto lo stage 2 del boot loader esegue il check dell'hardware, enumera i dispositivi collegati, esegue il mount del dispositivo root quindi carica i moduli necessari del kernel. Al termine il primo processo utente parte (init) e avviene l'inizializzazione del sistema ad alto livello. Questo è il processo di avvio di Linux in poche parole, di seguito si tenterà di scavare più a fondo esplorando i dettagli.

System Startup - BIOS

La fase di boot di Linux dipende dall'hardware su cui viene avviato; in alcune piattaforme viene utilizzato un ambiente di bootstrap specifico, alcuni esempi sono :

  • U-Boot - sta per Universal Bootloader, disponibile per diverse architetture tra cui PPC, ARM , x86 ecc... ; è un software free rilasciato sotto licenza GPL.
  • RedBoot - applicazione open source e permette il download e l'esecuzione di applicazioni embedded via seriale o ethernet.
  • Boot Monitor - è un piccolo programma interattivo che permette ad un utente di caricare un sistema operativo; risiede in ROM o in una locazione ben conosciuta su un disco; permette all'utente di ispezionare e fare il setup dell'hardware; tra i più famosi troviamo il BIOS ma ci sono anche Open Firmware  e Micromonitor .

Nel documento viene preso in considerazione il BIOS.

Sui PC il codice di boot iniziale è genericamente chiamato BIOS ed è estremamente semplice rispetto al firmware di un computer dedicato ad un sistema proprietario. In realtà i PC hanno più BIOS : uno per il computer stesso, uno per la scheda video, uno per la scheda SCSI, per i controller RAID, a volte anche per le schede di rete. I BIOS moderni risultano più 'intelligenti' rispetto al passato per cui l'intervento manuale è minimo ma in caso di necessità è possibile, tramite una combinazione di tasti (tipicamente si utilizza il tasto DEL ma ovviamente dipende dall'hardware in gioco) accedere ad una interfaccia di configurazione; l'utilizzo maggiore della quale è modificare la sequenza dei dispositivi di boot del PC. Su un PC su cui vogliamo eseguire il boot con Linux, il BIOS si avvia dall'indirizzo di memoria 0xFFFF0 e la prima operazione che esegue è il cosidetto Power On Self Test(POST) che ha il compito di di eseguire il check dell'hardware, in sostanza una autodiagnosi. Oltre al funzionamento della motherboard, il POST può verificare anche periferiche quali tastiera, mouse, ecc...

I passi che vengono eseguiti sono tipicamente i seguenti (da Wikipedia) :

  • verifica dell'integrità dello stesso codice del BIOS
  • determinazione della causa che ha innescato il processo di POST
  • individuazione, determinazione della dimensione e verifica della memoria primaria del sistema
  • individuazione, inizializzazione e catalogazione di tutti i bus ed i device del sistema
  • (se necessario) rilascio del controllo del processo a BIOS specializzati (ad esempio BIOS video)
  • rendere disponibile un'interfaccia utente per la configurazione del sistema
  • identificare, organizzare e selezionare i device pronti per la continuazione della fase di bootstrap
  • inizializzare il sistema come richiesto dal sistema operativo target

Il secondo step del BIOS è l'enumerazione dei device locali e l'inizializzazione degli stessi. Considerando il diverso utilizzo delle funzioni del BIOS, possiamo individuare due componenti : il codice che esegue il POST e i runtime services. Dopo che il POST viene completato esso viene rimosso dalla memoria mentre i runtime services restano disponibili per il sistema operativo, nel nostro caso Linux. Per consentire l'avvio di un sistema operativo, i runtime services cercano un dispositivo che sia attivo (active) e avviabile (bootable) seguendo l'ordine di preferenza impostato nei settaggi del CMOS.

I dispositivi da cui è possibile eseguire il boot sono : floppy disk, CDROM, una partizione di un hard disk, dispositivo di rete, USB flash memory. Tipicamente Linux viene avviato da un hard disk dove risiede il Master Boot Record (MBR) che contiene il boot loader principale e quando ciò avviene e il MBR viene caricato in memoria il BIOS gli lascia il controllo.

Stage 1 Bootloader - MBR

Il MBR (valore dei default dei settori degli hd = 512) corrisponde al primo settore del cilindro 0 della testina 0 dell'hard disk. Il boot loader primario che risiede nel MBR è una immagine di 512 bytes che contiene sia il codice del programma che una piccola tabella delle partizioni. Di seguito l'anatomia del MBR :

I primi 446 bytes sono il bootloader primario e contengono sia il codice eseguibile che il testo dei messaggi di errore; i 64 bytes successivi fanno riferimento alla partition table ovvero le informazioni sul partizionamento del disco.

Come si vede dalla immagine sopra, la partition table si compone di massimo 4 partizioni(4 primarie oppure 3 primarie e 1 estesa) per cui 16 bytes ogni partizione che contengono le seguenti informazioni :

  • 0 : Indicatore di boot (se attivo ha valore 80 esadecimale)
  • 1-3 : Testina, settore e cilindro del primo blocco della partizione
  • 4 : Identificazione del filesystem contenuto nella partizione
  • 5-7 : Testina, settore e cilindro dell'ultimo blocco della partizione
  • 8-11 : Numero blocchi prima della partizione
  • 12-15 : Numero blocchi che costituiscono la partizione

Hard Disk

Al fine di rendere più chiaro quanto esposto sopra facciamo un digressione sulla composizione di un Hard Disk.

L'immagine a destra indica l'organizzazione della memorizzazione dei dati su un hd

I dati sono generalmente memorizzati su disco seguendo uno schema di allocazione fisica ben definito in base al quale si può raggiungere la zona dove leggere/scrivere i dati sul disco. Uno dei più diffusi è il cosidetto CHS acronimo per il termine inglese Cylinder/Head/Sector (Cilindro/Testina/Settore); in questa struttura i dati sono memorizzati avendo come indirizzo fisico un numero per ciascuna delle seguenti entità fisiche:

  • Piatto : un disco rigido si compone di uno o più dischi paralleli, di cui ogni superficie, detta "piatto" e identificata da un numero univoco, è destinata alla memorizzazione dei dati.
  • Traccia : ogni piatto si compone di numerosi anelli concentrici numerati, detti tracce ciascuna identificata da un numero univoco.
  • Cilindro : l'insieme di tracce alla stessa distanza dal centro presenti su tutti i dischi è detto cilindro. Corrisponde a tutte le tracce aventi il medesimo numero, ma diverso piatto.
  • 'Settore : ogni piatto è suddiviso in "spicchi" radiali uguali ciascuno identificato da un numero univoco.
  • Blocco : l'insieme di settori posti nella stessa posizione in tutti i piatti.
  • Testina : Su ogni piatto è presente una testina per accedere in scrittura o in lettura ai dati memorizzati sul piatto; la posizione di tale testina è solidale con tutte le altre sugli altri piatti. In altre parole, se una testina è posizionata sopra una traccia, tutte le testine saranno posizionate nel cilindro a cui la traccia appartiene.

LBA

Con l'aumentare della capacità degli hard disk è emerso un limite in questi 16 bytes, in sostanza non sono sufficienti per identificare i valori elevati di testine, settori ecc... per cui si è ovviato agendo sui BIOS che sono in grado di utilizzare la traduzione dell'indirizzamento dei settori LBA (Logical Block Addressing). Il Logical block addressing, abbreviato LBA, è un sistema di accesso ai dati usato nei dischi fissi, introdotto per superare il limite dei 504 MiB  del precedente sistema CHS (cylinder-head-sector).

 


Tornando al MBR gli ultimi due bytes identificano quello che prende il nome di Magic Number e corrisponde al valore 0xAA55 ed ha la funzione di convalidare il MBR stesso.

E' altamente consigliabile eseguire un backup del MBR attraverso l'utilizzo del comando che segue da eseguirsi con i privilegi di root :

  • dd if=/dev/hda of=/mbr.bin bs=512 count=1

In sostanza il comand dd (Data Dump) così impartito non fa altro che leggere i primi 512 bytes dall'hard disk hda e scriverli nel file mbr.bin. Il ripristino è fattibile con il comando seguente da eseguirsi sempre con i diritti di root :

  • dd if=mbr.bin of=/dev/hda bs=512 count=1

L'obiettivo principale del boot loader primario è quello di trovare e caricare il boot loader secondario o Stage 2 boot loader.

Per fare questo esegue una ricerca di una partizione attiva tra quelle presenti nella partition table, quando la trova esegue lo scan delle restanti partizioni per assicurarsi che queste siano tutte inattive, a questo punto viene letto il record di boot dal dispositivo, messo in RAM ed eseguito.

Stage 2 Bootloader - GRUB

Lo stage 2 può essere chiamato in maniera più corretta : kernel loader. Il compito di questa fase è quello di caricare il kernel Linux e, opzionale, RAM disk iniziale. Il primo e il secondo stage del boot loader combinati insieme, in un ambiente x86, prendono il nome di Linux Loader (LILO) o Grand Unified Bootloader (GRUB). LILO è il boot loader tradizionale, risulta molto stabile e ben documentato ma presenta degli svantaggi che sono stati corretti in GRUB che ormai è di fatto utilizzato in quasi tutte le distribuzioni. Considerando l'importanza che ricopre GRUB per un corretto avvio del sistema, di seguito si cercherà di analizzarne i particolari.

GRUB

Il primo step per rendere GRUB il bootloader principale dipende se si sta installando un sistema Linux da zero o se questo è già installato sul PC. Tipicamente in fase di setup di un sistema viene richiesto dove e se installare GRUB permettendo di selezionare la destinazione. Vista la possibilità di decidere è possibile in ogni caso, procedere con l'installazione di GRUB tramite il comando :

  • grub-install '(hd0,0)' (gli apici sono necessari per una corretta interpretazione delle parentesi)

Uno dei particolari a cui porre attenzione è la diversa modalità di interpretazione degli hard disk e delle relative partizioni. Per indicare a GRUB il disco /dev/hda1 si deve scrivere (hd0,0) il primo numero indica il disco fisico (la numerazione parte da 0) il secondo indica la partizione (anche in questo caso si parte da 0). Altro esempio : /dev/hdb3 per GRUB è (hd1,2)

Il processo di boot avviene per stadi; speciali file immagine GRUB si occupano di ogni stadio, e lo stadio precedente contribuisce sempre all'esecuzione del successivo. Due di essi sono fondamentali, gli altri sono opzionali e dipendono dalla configurazione del sistema. Tra gli stadi opzionali esiste quello denominato Stage 1,5; Stage 1 può caricare direttamente lo Stage 2 oppure passare per quello intermedio 1.5 che farà da ponte. Come abbiamo già visto lo Stage 1 è quello riferito al MBR, mentre lo Stage 1.5 è importante in quanto comprende la semantica dei vari file system e permette di accedervi consentendo di individuare i file da caricare. Lo Stage 2 è il cuore di GRUB in quanto ha il codice per consentire l'avvio del sistema operativo vero e proprio. A destra è possibile vedere come si presenta il menu di GRUB.

Con i tasti cursore è possibile selezionare una delle voci del menù mentre con il taso 'c' si accede alla riga di comando di GRUB e con 'e' si apre un editor dove è possibile modificare la voce del menù selezionata. Questi sono potenti strumenti per modificare al volo le configurazioni oppure eseguire il boot manuale. La riga di comando è dotata di funzionalità simili alla shell, come il completamento dei comandi e lo spostamento del cursore. Per visualizzare un elenco di comandi è sufficiente premere il tasto <Tab>. Come abbiamo indicato sopra, da riga di comando è possibile eseguire il boot di un sistema operativo non in elenco, manualmente, di seguito i comandi da impartire :

  • grub> kernel /vmlinuz-2.6.24-19
  • grub> initrd initrd.img-2.6.24-19
  • grub> boot

Uncompressing Linux... Ok, booting the kernel.

Nel caso non si sia a conoscenza del nome del kernel è possibile utilizzare / e il tasto <Tab> per elencare la lista dei kernel e delle immagini initrd.

Di default, GRUB legge la configurazione da /boot/grub/grub.conf oppure, come nel caso di ubuntu, menu.lst, ecco un esempio di file di configurazione :

  1. default 0
  2. timeout 10
  3. BEGIN AUTOMAGIC KERNELS LIST
  4. title Ubuntu 8.04.1, kernel 2.6.24-19-generic
  5. root (hd0,1)
  6. kernel /boot/vmlinuz-2.6.24-19-generic root=UUID=efea7852-6933-4a51-918c-4264770e961e ro quiet splash
  7. initrd /boot/initrd.img-2.6.24-19-generic
  8. quiet
  9. END DEBIAN AUTOMAGIC KERNELS LIST
  10. title Windows Vista/Longhorn (loader)
  11. root (hd1,0)
  12. savedefault
  13. makeactive
  14. chainloader +1

Le righe degne di nota sono state numerate per semplificare la lettura e consentire di associare una spiegazione.

  1. Questa direttiva dice a GRUB quale voce avviare automaticamente. La numerazione parte da 0, il file sopra così com'è contiene due voci, per cui si avvierà la prima.
  2. Significa che GRUB avvia automaticamente la selezione predefinita dopo 10 secondi. E' possibile interrompere questo premendo un tasto qualsiasi sulla tastiera prima che scada l'intervallo.
  3. Va associata alla riga 9; quando viene installato un nuovo kernel contenuto in un pacchetto .deb viene eseguito in automatico il programma 'update-grub' che cerca nuovi kernel nella cartella /boot e li aggiunge nel file di configurazione /boot/grub/menu.lst
  4. Utilizzata per visualizzare un titolo o una breve descrizione. Il campo segna l'inizio di una nuove voce di boot in GRUB.
  5. Indica al kernel qual'è la partizione contenente la directory radice del sistema (root filesystem).
  6. Permette di inserire il percorso del file contenente l'immagine del kernel con i relativi argomenti, nel caso specifico abbiamo :
    • 'root' indica dove trovare il root filesystem e in questo caso è indicato con il parametro UUID (*) e il relativo valore ma è la stessa cosa che scrivere /dev/hda1 per esempio.
    • 'ro' accede in sola lettura alla partizione contenente la root
    • 'quiet' associato a 'splash' consente di vedere un'immagine anziché tutti i messaggi del caricamento di Linux, questi si possono rivedere tramite il comando 'dmesg' una volta che il sistema è avviato.
  7. Questa opzione consente di caricare i moduli del kernel da un'immagine e non da i moduli in lib/modules; nel caso di Ubuntu il kernel utilizza una di queste immagini.ATTENZIONE: Un kernel partirà solo con la sua immagine initrd, se provate ad usare immagini initrd di altri kernel il sistema non partirà dando un Kernel Panic.Analogamente se cercate di fare partire un kernel che necessita di initrd, senza initrd il sistema andrà ancora in Kernel Panic.
  8. Vedi punto 6.
  9. Vedi punto 3.
  10. Alcuni sistemi operativi come Windows necessitano di una configurazione particolare per essere avviati in quanto hanno delle routine specifiche che si occupano dell'avvio.
  11. Indica la partizione dove trovare il bootloader del sistema operativo non Linux.
  12. E' possibile inserirlo in ogni blocco di avvio di un kernel va in coppia con il comando default (vedi punto 1), se quest'ultimo viene impostato con 'save' al posto del valore numerico(in questo caso 0), all'avvio GRUB sceglierà il kernel scelto nel precedente boot.
  13. Rende attiva la partizione (necessario per Windows).
  14. Carica il boot loader dalla posizione indicata, nel caso specifico il settore 1 della prima partizione del drive principale.

(*) UUID : tipicamente siamo abituati a vedere le periferiche che interagiscono con il sistema nella cartella /dev e in particolare gli hard disk, ma esiste un metodo di riconoscimento per il sistema meno noto chiamato appunto UUID. Esso è una rappresentazione in esadecimale che descrive correttamente i cluster che questa partizione racchiude, quindi dà al nostro sistema precise coordinate sul dove inizia e dove finisce una determinata partizione. Per determinare l'UUID utilizzare il seguente comando :

  • $ sudo /lib/udev/vol_id /dev/sda3 | grep UUID

 


Dopo la digressione su GRUB, riprendiamo da dove avevamo interrotto. Come abbiamo visto, il grosso vantaggio di GRUB è che questo conosce i filesystem Linux per cui è in grado di avviare un kernel Linux da una partizione ext2 o ext3. Con lo Stage 2 del boot loader caricato in memoria, viene consultato il file system e le immagini del kernel e initrd vengono caricate in memoria. Lo Stage 2 invoca l'immagine del kernel e le lascia il controllo e così inizia il cosiddetto Kernel Stage.

Kernel - Linux

Tipicamente il kernel che viene caricato non è un eseguibile ma bensì una immagine che contiene all'inizio della stessa una routine che consente le seguenti operazioni :

  • la decompressione il posizionamento in memoria alta del kernel
  • se presente un'immagine initrd, la sposta in memoria e lo annota per una fase successiva
  • una chiamata al kernel in modo da avviarne il boot

A questo punto iniziano una serie di complesse funzioni che è possibile vedere nel flusso a destra.

Tali funzioni richiedono conoscenze di programmazione che esulano dal contesto del documento. Durante il boot del kernel, l'initrd caricata in precedenza, viene montata e utilizzata come filesystem temporaneo e permette al kernel di eseguire il boot completo senza montare nessun dispositivo fisico. Solo al termine del boot, initrd lascia il posto al vero filesystem che viene montato in quanto ora il kernel è in grado di accedere alle periferiche. In pratica, initrd ha il compito di caricare i moduli che consentono al kernel di accedere ai dischi, farne il mount, ma anche di caricare i driver per gli altri componenti hardware.

INIT e i RUNLEVEL - User-space

Dopo che il kernel è stata avviato e inizializzato, lo stesso kernel avvia il primo processo non-kernel : init

Questo è il primo programma invocato che è compilato con librerie standard C. All'avvio init può impostare il sistema in modalità monoutente oppure multiutente dove si occupa di abilitare il login sui dispositivi come, ad esempio, le seriali; fa anche da supervisore per la procedura di login grafico che consente agli utenti di entrare direttamente in X window. INIT legge il proprio file di configurazione chiamato inittab, tipicamente residente in /etc, il quale determina quello che viene definito 'Runlevel'. Quest'ultimo rappresenta un particolare insieme di servizi che il sistema deve eseguire.

I runlevel tipicamente conosciuti vanno da 0 a 6 :

  • 0 Ferma il sistema
  • 1 Entre in modalità singolo utente (no network)
  • 2 Modalità multiutente ma senza NFS
  • 3 Modalità multiutente completa
  • 4 Non utilizzato
  • 5 Come il 3 ma con il login grafico
  • 6 Riavvia il sistema

Esiste un particolare runlevel, denominato S, che va a risolvere il problema di sicurezza legato al runlevel 1 ovvero fa partire il sistema in modalità monoutente ma chiede la password di root. In realtà i runlevel supportati da Linux sarebbero 10 ma dal 7 al 9 non vengono utilizzati.

Il valore del runlevel viene definito nel file inittab attraverso il seguente comando :

  • id:2:initdefault:

Quando il PC si avvia, init procede dal runlevel 0 fino al runlevel di default e per il passaggio da un'altro init esegue le azioni indicate nel file inittab. La stessa cosa accade allo spegnimento del PC ma in modo inverso ovviamente. Per associare le istruzioni del file inittab a qualcosa di più flessibile, Linux impiega un ulteriore livello di astrazione nella forma di uno script di 'cambiamento di runlevel'. Tutto questo viene sempre richiamato da inittab :

  • l1:1:wait:/etc/init.d/rc 1
  • l2:2:wait:/etc/init.d/rc 2
  • l3:3:wait:/etc/init.d/rc 3
  • l4:4:wait:/etc/init.d/rc 4
  • l5:5:wait:/etc/init.d/rc 5
  • l6:6:wait:/etc/init.d/rc 6

Gli script di avvio dei vari demoni risiedono tipicamente all'interno della cartella /etc/init.d e prendono il nome RC che sta per RunCommand, ma non vengono richiamati direttamente, vengono utilizzate delle cartelle per ogni runlevel : /etc/rcx.d dove x è un valore che va da 0 a 6 per cui avremo 7 cartelle. Ogni cartella contiene i link agli script reali, che come abbiamo già detto, sono in/etc/init.d.

Se andiamo a visualizzare il contenuto di uno delle cartelle /etc/rcx.d troveremo qualcosa di simile :

  • lrwxrwxrwx 1 root root 13 2008-04-27 14:04 K01gdm -> ../init.d/gdm
  • lrwxrwxrwx 1 root root 17 2008-04-27 14:04 K01usplash -> ../init.d/usplash
  • lrwxrwxrwx 1 root root 17 2008-09-12 22:06 K09apache2 -> ../init.d/apache2
  • lrwxrwxrwx 1 root root 16 2008-04-27 14:04 K16dhcdbd -> ../init.d/dhcdbd
  • lrwxrwxrwx 1 root root 16 2008-04-27 14:04 K20apport -> ../init.d/apport
  • lrwxrwxrwx 1 root root 22 2008-04-27 14:04 K20avahi-daemon -> ../init.d/avahi-daemon
  • lrwxrwxrwx 1 root root 14 2008-09-09 22:22 K20wicd -> ../init.d/wicd
  • lrwxrwxrwx 1 root root 17 2008-07-14 22:10 K20winbind -> ../init.d/winbind
  • lrwxrwxrwx 1 root root 15 2008-09-12 22:05 K21mysql -> ../init.d/mysql
  • lrwxrwxrwx 1 root root 19 2008-09-12 22:05 K22mysql-ndb -> ../init.d/mysql-ndb
  • lrwxrwxrwx 1 root root 23 2008-09-12 22:05 K23mysql-ndb-mgm -> ../init.d/mysql-ndb-mgm
  • lrwxrwxrwx 1 root root 20 2008-06-04 20:42 K25hwclock.sh -> ../init.d/hwclock.sh
  • lrwxrwxrwx 1 root root 13 2008-04-27 14:04 K39ufw -> ../init.d/ufw
  • lrwxrwxrwx 1 root root 20 2008-04-27 14:04 K50alsa-utils -> ../init.d/alsa-utils
  • lrwxrwxrwx 1 root root 26 2008-04-27 14:04 K59mountoverflowtmp -> ../init.d/mountoverflowtmp
  • lrwxrwxrwx 1 root root 21 2008-04-27 14:04 K99laptop-mode -> ../init.d/laptop-mode
  • lrwxrwxrwx 1 root root 22 2008-04-27 14:04 S15wpa-ifupdown -> ../init.d/wpa-ifupdown
  • lrwxrwxrwx 1 root root 18 2008-04-27 14:04 S20sendsigs -> ../init.d/sendsigs
  • lrwxrwxrwx 1 root root 17 2008-04-27 14:04 S30urandom -> ../init.d/urandom
  • lrwxrwxrwx 1 root root 22 2008-04-27 14:04 S31umountnfs.sh -> ../init.d/umountnfs.sh
  • lrwxrwxrwx 1 root root 18 2008-04-27 14:04 S40umountfs -> ../init.d/umountfs
  • lrwxrwxrwx 1 root root 20 2008-04-27 14:04 S60umountroot -> ../init.d/umountroot
  • lrwxrwxrwx 1 root root 14 2008-04-27 14:04 S90halt -> ../init.d/halt

Da notare la nomenclatura dei file che presentano il prefisso K o S e un numero. Quando si passa ad un runlevel più alto, init esegue con il parametro Start tutti gli script che iniziano con S, in ordine numerico crescente. Nel passaggio ad un runlevel più basso, init esegue con il parametro Stop tutti gli script che iniziano con K, in ordine decrescente. Questo metodo permette di decidere quali demoni avviare e in quale sequenza, un esempio pratico : non ha alcun senso avviare il demone sshd se prima non si attivano le interfacce di rete. Gli script e la posizione degli stessi nel file system cambiano a seconda della distribuzione.

Fabrizio Canonici