• Non ci sono risultati.

Figura 4.2: Android framework

(vedi Figura 4.3). Il primo componente è quello che ho spiegato poco fa, detto Application Framework. Il livello inferiore, detto Binder IPC Proxies contiene un meccanismo che permette all’Application Framework di superare i limiti dei proces- si e chiamare in Android i servizi di sistema, da API di alto livello. Esso è detto IPC, cioè InterProcess Communication. Subito sotto vi sono i servizi di sistema che permettono alle API di alto livello di comunicare con l’hardware. Per esempio, ci sono servizi come il Windows Manager, l’Activity Manager e quelli per i contenuti multimediali. Nel penultimo livello c’è l’Hardware Abstraction Layer (HAL), come in Figura 4.4, cioè un’interfaccia standard che permette ad Android di chiamare i dri- ver, facendo si che l’implementazione di basso livello e l’hardware siano separati dal software presente nei livelli superiori. Quando un produttore utilizza un suo compo- nente, implementa la parte dell’HAL e il driver necessario. Android non standardizza l’interazione tra l’elemento nell’HAL e il driver, ma richiede che siano rispettati gli standard per far si che il sistema operativo possa comunicare con il nuovo elemento. Di solito le implementazioni dell’HAL sono salvate in librerie condivise, cioè file “.so”. Infine vi è il kernel, basato su Linux, ma con alcune modifiche come i wakelock, una gestione più aggressiva della memoria, il Binder IPC driver ed altre caratteristiche utili in ambienti embedded. Nel corso di questo capitolo e dei successivi, analizzerò più nel dettaglio il kernel di Android.

4.2 Il processo di boot in Android

In questa sezione mostrerò il processo di boot di Android, ma per comprenderla meglio riporto una breve sintesi della struttura delle partizioni [69].

4. Architettura, kernel e Build System di Android

Figura 4.3: Android framework nel dettaglio

4.2. Il processo di boot in Android

Figura 4.5: Processo di boot completo

1. /boot: include kernel e ramdisk e quindi è essenziale per avviare il sistema operativo.

2. /system: contiene Android, il kernel e ramdisk. Rimuoverla vuol dire cancellare il sistema operativo e rendere impossibile l’avvio del dispositivo.

3. /recovery: utile per i backup e può essere usata come procedura alternativa per il boot, per esempio per ripristinare un backup.

4. /data: dati dell’utente e applicazioni installate. È la partizione cancellata quando si fa il factory reset, cioè si ritorna alle impostazioni di fabbrica. 5. /cache: usata da Android per salvare elementi a cui accede spesso. Può essere

cancellata senza rischi.

6. /misc: impostazioni di Android, tra cui le configurazioni hardware e dell’ope- ratore.

7. /sdcard rappresenta la memoria usata dall’utente, che può essere in una parti- zione o in una scheda esterna.

8. altre che dipendono dal produttore.

Nel momento in cui si accende il dispositivo premendo l’apposito pulsante, iniziano una serie di eventi sequenziali che portano all’avvio di Android. Il questo lavoro di testi mostrerò queste fasi (vedi Figura 4.5) in modo sintetico e schematico [66, 86].

4. Architettura, kernel e Build System di Android

Figura 4.6: Processo di boot - passo 1

Fase 1: Avvio del sistema

Acceso il dispositivo, inizia la procedura divisa nelle due fasi, in Figura 4.6. 1. Il codice non modificabile scritto nella BootROM (che di solito è un chip de-

dicato) rileva il Boot media (NAND). Questo serve per determinare dove si troverà il first stage Bootloader (cioè la prima parte del Bootloader).

2. La BootROM tenta di caricare il first stage Bootloader nella Internal RAM. Una volta fatto, il codice nella BootROM esegue un’istruzione di salto (jump) e l’esecuzione passa alla fase successiva.

Fase 2: Bootloader

Il Bootloader è in due fasi (o stage), cioè first stage Bootloader e second stage Bootloader. In Figura 4.7 è rappresentata la procedura in dettaglio.

1. Il first stage Bootloader rileva e imposta l’External RAM.

2. Una volta che l’External RAM è disponibile e il sistema è pronto ad eseguire operazioni, il first stage Bootloader esegue il caricamento della seconda fase nella External RAM.

3. Il second stage Bootloader può contenere codice per impostare il filesystem, memoria aggiuntiva ed il supporto di rete. Inoltre, può essere utile anche per attivare protezioni della memoria e di sicurezza sui moderni dispositivi1.

1Spesso in ambiente embedded, le società che producono i dispositivi usano Bootloader pro-

prietari e bloccati. L’obiettivo è impedire la modifica del software, per esempio come fa Samsung.

4.2. Il processo di boot in Android 4. Ricerca il kernel Linux per avviarlo, lo prende dal Boot media e lo mette in RAM, cioè carica la zImage, il file binario compresso del kernel. In esso vi è anche tutta la descrizione dell’hardware.

5. Esegue un’operazione di salto al kernel Linux e svolge alcune procedure di decompressione. Infine il controllo è passato al kernel.

Figura 4.7: Processo di boot - passo 2

Nei dispositivi più vecchi, sono stati usati usati due registri: r1 per salvare il tipo di macchina ed r2 per l’ATAGS che contiene informazioni come la posizione e la dimensione della memoria. In quelli più moderni, il kernel non contiene più le informazioni sull’hardware, che invece sono in un file binario a parte, detto Device Tree Blob (DTB). Di conseguenza, il Bootloader carica due file binari, cioè la zImage e il DTB, passando l’indirizzo di memoria di quest’ultimo attraverso il registro r2. Il tipo di macchina non è più necessario e quindi il registro r1 non è più utilizzato. Per architetture ARM, tutti i DTS sono in arch/arm/boot/dts, cioè sia i “.dts” con informazioni sulla board e i “.dtsi” per informazioni sul SoC. Questi file sono compilati da un programma chiamato Device Tree Compiler, il cui codice sorgente si trova in scripts/dtc. Quindi, il DTB generato dal compilatore è caricato dal Bootloader e letto dal kernel al momento del boot. Per maggiori informazioni e la spiegazione del linguaggio di descrizione hardware DT vedere [78].

Fase 3: Kernel Linux

Il kernel si avvia in modo molto simile sia in Android, sia in altri sistemi (vedi Figura 4.8).

1. Una volta che Memory Management Unit (MMU) e cache sono inizializzate, il sistema sarà in grado di usare la memoria virtuale e lanciare i processi nello spazio dell’utente (user space).

4. Architettura, kernel e Build System di Android

2. Il kernel guarda nella radice del filesystem per trovare la procedura di init e l’avvia come un processo utente.

Figura 4.8: Processo di boot - passo 3

Fase 4: Il processo di init

Init è il primo vero processo eseguito ed ha due responsabilità (vedi Figura 4.10). • Fa il mount di cartelle come /sys, /dev, /proc, tramite procfs, sysfs e cgroupfs [116]. Questi ultimi tre sono tutti filesystem virtuali mantenuti dal kernel in esecuzione. Essi non sono usati per il salvataggio di dati, infatti le strutture dati sono nel kernel. Per esempio, procfs è il modo tradizionale con cui il kernel esporta informazioni su se stesso nello spazio dell’utente. Tipicamente, queste informazioni sono viste come file accessibili o log per ottenere informazioni. • Esegue lo script init.rc, che esegue il mount di diverse altre “immagini” e file-

system virtuali, come in Figura 4.9. Questo perché ognuno ha scopi differenti. Per esempio, ramdisk.img è una “immagine” compressa prima di essere caricata in RAM dal kernel, che viene poi montata come un filesystem di root in sola lettura.

Fasi 5 e 6: Zygote, Dalvik e System server

Queste fasi non fanno parte del mio lavoro di tesi, quindi non le considererò. Comunque, in esse è avviata la parte Java di Android, c’è la gestione delle macchine virtuali Dalvik, una per ogni app ed infine sono gestiti ed avviati i servizi di sistema.