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 <tlambert@primenet.com>
(ID del messaggio:
<199906020108.SAA07001@usr09.primenet.com>
).
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
<questions@FreeBSD.org>.
Per domande su questa documentazione, invia una e-mail a
<doc@FreeBSD.org>.