Questo articolo nasce da una mia recente rilettura della famosa diatriba Kernel Monolitico vs MicroKernel, tra il giovinastro Linus Torvalds ( Kernel Monolitico ) ed il professore rinomato Andy Tanenbaum ( MicroKernel ). Vi rimando a questo link per avere una idea sul loro scambio di opinioni a riguardo
http://www.dina.dk/~abraham/Linus_vs_Tanenbaum.html
Da ormai tre anni ho scelto di usare Mac, in principo la scelta e’ stata dettata dalla necessita’ di liberare la mia scrivania da tutti quei fili penzolanti ( mia madre voleva uccidermi 😛 ) e dal fatto che iMac ha il suo fascino ( soprattutto da quando gira su IA64 ) e la sua eleganza. Con il passare del tempo sono rimasto ammaliato dalla bellezza e semplicita’ del Sistema Operativo di Cupertino, la potenza di un sistema BSD-based con un interfaccia accattivante e’ stata davvero una bella scoperta, fino ad arrivare a documentarmi sull’architettura alla base di tale sistema e cercare di capire qualcosa in piu’…
Il cuore di Mac OS X e’ il kernel XNU, il quale puo’ essere visto come un insieme di piu’ componenti : il core basato su Mach 3, le features supplementari offerte da FreeBSD 5, la personalita’ di un Sistema Operativo basato su BSD ed un ambiente basato su un sistema object-oriented per quanto concerne i driver. In effetti il Kernel di Mac OS X e’ molto di piu’ che XNU, infatti esistono molti driver che non risiedono nel core di XNU ma derivano dai packages Darwin.
Per avere un idea delle estensione kernel che girano sul vostro sistema Mac OS X basta dare il seguente comando:
$ kextstat
oppure andare nella seguente cartella per vedere quali estensioni sono presenti
/System/Library/Extensions/
Un attimo pero’.. io ho sempre saputo che il cuore di Mac OS X fosse a MikroKernel.. ora questa teoria sembra vacillare 🙁
Xnu Is Not a Microkernel
All kernel components reside in a single kernel address space in Mac OS X. Although the kernel is
modular and extensible, it is still monolithic. Nevertheless, note that the kernel closely works with a
few user-space daemons such as dynamic_pager, kextd, and kuncd.
La citazione deriva direttamente dalla documentazione ufficiale Apple. Vedremo nei prossimi paragrafi cosa puo’ essere considerato a MicroKernel e cosa no.
Mach
Se il kernel XNU e’ il core di Mac OS X, Mach puo’ essere considerato il core di XNU.
Nato da un progetto di Rick Rashid e Avie Tevaniane’ alla Carnegie Mellon University con il preciso compito di essere un Sistema Operativo UNIX-based compatibile, e’ il responsabile dell’astrazione del sistema hardware, un metodo molto comune nei moderni Sistemi Operativi che serve per disaccoppiare l’hardware sottostante con lo strato software.
Il cuore del Kernel Mach e’ a MicroKernel, tale kernel e’ orientato alla comunicazione tramite il meccanismo IPC ( Inter-Process Communication ) e con il pieno supporto al multiprocessing. Tale scelta implementativa e’ stata fatta per cercare di diminuire l’ammontare del codice che gira a livello kernel e permettere agli altri moduli del kernel ( FileSystem, Networking, User Interface ) di poter girare a livello user in modo da non creare problemi critici al sistema in caso di failure.
Nelle prima versioni di Mach basato sulle versione UNIX, il livello UNIX girava come server in un tash separato. Adesso, in Mac OS X, Mach e BSD girano nello stesso spazio di indirizzi.
Mach offre una intefaccia trasparente al livello applicativo per i servizi a basso livello, eccovi una lista degli aspetti di cui Mach e’ responsabile:
- Astrazione hardware
- Gestione del processore, incluso lo scheduling dei processi ed SMP
- Multitasking preempitivo, incluso il supporto ai threads ed ai tasks
- Gestione delle memoria virtuale, del paging, protezione della memoria
- Meccanismi IPC di basso livello, che sono alla base dello scambio dei messaggi nel kernel
- Supporto al real-time
- Supporto al debugging del kernel
Mach e’ spesso considerato a MicroKernel, ma nelle versione precedenti al Mach 3 il suo sistema era prettamente monolitico. Anche se Apple usa una implementazione basata su Mach 3, XNU non usa Mach come un MicroKernel tradizionale a riprova di questo sia il la parte di BSD che quella di I/O girano allo stesso livello di Mach, e tutti condividono lo stesso spazio di indirizzi.
BSD
Il kernel di Mac OS X include molte linee di codice derivanti direttamente da FreeBSD ( circa un milione di linee di codice ). Come detto in precedenza, tale codice gira allo stesso livello di Mach. Il codice incorporato da FreeBSD, per poter funzionare correttamente con Mach ed il Kit I/O, e’ stato modificato in buona parte. Nonostante tali modifiche, alcune caratteristiche tipiche dei sistemi BSD sono rimaste intatte:
- Il modello dei processi BSD-style
- Segnali
- user ID, permessi e le policy di sicurezza di base
- APIs POSIX
- API asincrone di I/O
- System Call BSD-style
- TCP/IP stack, BSD socket ed il firewall
- Virtual File System (VFS) e numerosi file system indipendenti
- System V
- Framework Cryptographic
- ACL (Access Control List)
Per avere un idea di quanto sia complicata la coesistenza tra lo stile BSD e quello Mach pensate al seguente esempio. Nei sistemi BSD unita’ fondamentale di esecuzione e’ il processo, mentre in Mach e’ il Thread. Tale disparita’ e’ stata superata associando ad ogni singolo processo di BSD un task Mach che consiste esattamente in un Thread. Quando e’ chiamata una System Call come fork(), il codice BSD presente nel kernel usa le chiamate a Mach per crere un task ed una struttura Thread.
Un altro esempio di questa disparita’ tra il sistema BSD e quello Mach e’ la gestione della sicurezza, in Mach viene gestito tramite i right port, mentre in BSD e’ usato il modello dei diritti di accesso sui processi. La disparita’ tra i due modelli e’ stata la causa di numerosi vulnerabilita’ di Mac OS X sulla escalation dei privilegi :P. Per tale motivo sono state inserite delle ulteriori traps tra lo strato Mach e le System Call effettuate dalle applicazioni a livello kernel.
I/O Kit
I/O Kit e’ l’open source, object-oriented, framework dei device driver responsabile della gestione e del caricamento dinamico dei device driver. Questi drivers vengono usati per il caricamento dinamico nel kernel dei moduli necessari per il corretto funzionamento dei differenti hardware.
unicondor@unicondor:~> kextstat
Index Refs Address Size Wired Name (Version) <Linked Against>
1 74 0 0 0 com.apple.kpi.bsd (10.6.0)
2 4 0 0 0 com.apple.kpi.dsep (10.6.0)
3 98 0 0 0 com.apple.kpi.iokit (10.6.0)
4 105 0 0 0 com.apple.kpi.libkern (10.6.0)
5 90 0 0 0 com.apple.kpi.mach (10.6.0)
6 29 0 0 0 com.apple.kpi.private (10.6.0)
7 47 0 0 0 com.apple.kpi.unsupported (10.6.0)
8 0 0 0 0 com.apple.kernel.6.0 (7.9.9)
9 0 0 0 0 com.apple.kernel.bsd (7.9.9)
10 0 0 0 0 com.apple.kernel.iokit (7.9.9)
11 0 0 0 0 com.apple.kernel.libkern (7.9.9)
12 1 0 0 0 com.apple.kernel.mach (7.9.9)
13 13 0x913000 0x4000 0x3000 com.apple.iokit.IOACPIFamily (1.3.0) <7 6 4 3>
14 23 0x927000 0x11000 0x10000 com.apple.iokit.IOPCIFamily (2.6) <7 5 4 3>
15 2 0x10ed000 0x42000 0x41000 com.apple.driver.AppleACPIPlatform (1.3.5) <14 13 7 6 5 4 3>
16 0 0x1364000 0x1e000 0x1d000 com.apple.driver.AppleIntelCPUPowerManagement (105.13.0) <7 6 5 4 3 1>
17 8 0x1166000 0x18000 0x17000 com.apple.iokit.IOStorageFamily (1.6.2) <7 6 5 4 3 1>
18 0 0x14e5000 0x11000 0x10000 com.apple.driver.DiskImages (289) <17 7 6 5 4 3 1>
19 0 0x15ee000 0x8000 0x7000 com.apple.nke.applicationfirewall (2.1.11) <7 6 5 4 3 1>
20 0 0x1a22000 0x3000 0x2000 com.apple.security.TMSafetyNet (6) <7 6 5 4 2 1>
21 2 0x1a25000 0x3000 0x2000 com.apple.kext.AppleMatch (1.0.0d1) <4 1>
22 0 0x1a28000 0x5000 0x4000 com.apple.security.quarantine (0) <21 7 6 5 4 2 1>
Come potete vedere, molte delle entita’ della lista sono caricate all’indirizzo zero. Questo significa che sono parte del Kernel e non sono dei veri e propri device driver ( Ex. non possono essere unloaded). Il primo device driver nel mio caso e’ il 13.
Supponiamo di voler trovare e caricare il modulo kernel responsabile del File System MS-DOS:
$ kextfind -bundle-id -substring ‘msdos’
/System/Library/Extensions/msdosfs.kext
Ora che sappiamo il suo nome, possiamo caricare il modulo in Mac OS X
$ sudo kextload /System/Library/Extensions/msdosfs.kext
kextload: /System/Library/Extensions/msdosfs.kext loaded successfully
Per controllare che sia stato caricato con successo:
$ kextstat | grep msdos
126 0 0x346d5000 0xc000 0xb000
com.apple.filesystems.msdosfs (1.5.2) <7 6 5 2>
Il quale ci dice che e’ il driver numero 126 ad essere stato caricato, ci sono zero referenze al driver ( nessuno lo sta usando ) , ed e’ stato caricato all’indirizzo 0x346d5000 ed ha una grandezza 0xc000 e che uccupa in memoria kernel bytesl.
Infine possiamo fare unload del driver digitando:
$ sudo kextunload com.apple.filesystems.msdosfs
kextunload: unload kext /System/Library/Extensions/msdosfs.kext
succeeded
Spero di non avermi annoiato troppo… anche se il semplice fatto di essere arrivati fin qui, come me, dimostra che amate queste tipo di letture 😀