Se sei curioso di come funziona la compatibilità con i binari di Linux, questa è la
sezione da leggere. Molto di ciò che segue è basato pesantemente su una email scritta a
mailing
list di chiacchiere su FreeBSD da Terry Lambert <[email protected]>
(ID del
messaggio: <[email protected]>).
FreeBSD ha una astrazione chiamata un “loader della classe di esecuzione”. Questo ` un cuneo nella chiamata di sistema execve(2).
Cosa succede è che FreeBSD ha una lista di loader, piuttosto che un singolo loader con un ritorno nel loader #!, per lanciare qualunque inteprete o script della shell.
Storicamente, l'unico loader nella piattaforma UNIX® esaminava il numero magico (generalmente i primi 4 o 8 byte del file) per vedere se il binario fosse conosciuto dal sistema e, nel caso, invocava il loader del binario.
Se non era un tipo di binario per il sistea, la chiamata execve(2) ritornava un errore, e la shell tentava di avviare eseguendolo come comando della shell.
L'assunzione era un default, “qualunque fosse la shell”.
Più tardi, è stato fatto un hack per sh(1) per esaminare i primi due caratteri. Se erano :\n, allora invocava la shell csh(1) (crediamo sia stata SCO a fare per prima questo hack).
Ciò che ora fa FreeBSD è scorrere una lista di loader, con un loader #! generico che riconosce gli interpreti dai caratteri che seguono lo spazio successivo vicino alla fine, seguito da un ritorno a /bin/sh.
Per il supporto alle ABI di Linux, FreeBSD vede il numero magico come un binario ELF (a questo punto non fa distinzione tra FreeBSD, Solaris™, Linux, o qualunque altro SO che ha un tipo di immagine ELF).
Il loader di ELF cerca un marchio specializzato, che ` una sezione di commento nell'immagine ELF e che non è presente sui binari ELF SVR4/Solaris.
I binari di Linux, per funzionare, devono essere marchiati come tipo Linux da brandelf(1):
# brandelf -t Linux file
Quando viene fatto questo, il loader ELF vedrà il marchio di Linux sul file.
Quando il loader ELF vede il marchio di Linux, il loader sostituisce un puntatore nella struttura proc. Tutte le chiamate di sistema sono indicizzate attraverso questo puntatore (in un sistema UNIX tradizionale questo sarebbe l'array di strutture sysent[], contentente le chiamate di sistema). In aggiunta;, il processo è etichettato per un trattamento speciale del vettore trappola per il codice del segnale di lancio, e molti altri (minori) aggiustamenti che sono gestiti dal modulo Linux del kernel.
Il vettore delle chiamate di sistema di Linux contiene, tra le altre cose, una lista di valori sysent[] i cui indirizzi risiedono nel modulo del kernel.
Quando una chiamata di sistema è fatta dal binario di Linux, il codice trappola derefereizia il puntatore alla funzione della chiamata di sistema dalla struttura proc, e prende i punti di ingresso delle chiamate di sistema di Linux, non di FreeBSD.
In più, la modalità Linux ridefinisce la
root dinamicamente; questo, in effetti, è quello che fa l'opzione union
al montaggio del file system (non il tipo di file system unionfs!). Un tentativo viene prima fatto per cercare il file nella
directory /compat/linux/original-path, quindi, solo se fallisce, la ricerca ` fatta nella directory
/original-path. Questo
assicura che possano funzionare i binari che per richiedono altri binari (p.e., la
toolchain di Linux può funzionare tutta sotto il supporto ABI di Linux). Questo significa
anche che i binari di Linux possono caricare ed eseguire binari di FreeBSD, se non sono
presenti i corrispondenti binari di Linux, e che puoi mettere un comando uname(1) nell'albero
della directory /compat/linux per essere sicuro che i binari di
Linux non possano capire che non stanno girando sotto Linux.
In effeti c'è un kernel Linux nel kernel FreeBSD; le varie funzioni sottostanti che implementano tutti i servizi forniti dal kernel sono identiche sia nelle definizioni delle tabelle delle chiamate di sistema di FreeBSD che di Linux: le operazioni sul file system, le operazioni nella memoria virtuale, la consegna dei segnali, le IPC System V, ecc… L'unica differenza è che i binari di FreeBSD prendono le funzioni colla di FreeBSD, e i binari di Linux prendono le funzioni colla di Linux (molti dei vecchi SO hanno solo le loro funzioni colla: gli indirizzi delle funzioni in un array di strutture sysent[] statico globale, invece che indirizzi di funzioni dereferenziate da un puntatore inizializzato dinamicamente nella struttura proc del processo che fa la chiamata).
Qual è la ABI nativa per FreeBSD? Non importa. Essenzialmente l'unica differenza è che (attualmente: questo potrebbe facilmente essere cambiato in distribuzioni future, e probabilmente sarà fatto) le funzioni colla di FreeBSD sono collegate staticamente nel kernel, e le funzioni colla di Linux possono essere collegate staticamente o vi si può accedere attraverso un modulo del kernel.
Si, ma è davvero emulazione? No. è implementazione delle ABI, non emulazione. Non è coinvolto nessun emulatore (o simulatore, per evitare la prossima domanda).
Allora perché talvolta viene chiamata “emulazione Linux”? Per rendere difficile vendere FreeBSD! Seriamente, è perché l'implementazione storica è stata fatta in un momento in cui non c'era altro termine per descrivere ciò che stava succedendo; dire che FreeBSD lanciava i binari di Linux non era vero, se non compilavi il codice o caricavi un modulo, e c'era bisogno di un termine per descrivere cosa veniva caricato— da qui “l'emulatore Linux”.
Questo, ed altri documenti, possono essere scaricati da ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.
Per domande su FreeBSD, leggi la documentazione prima di contattare <[email protected]>.
Per domande su questa documentazione, invia una e-mail a <[email protected]>.