Prima di approfondire la definizione di una chiamata di sistema Linux ed esaminare i dettagli della sua esecuzione, è meglio iniziare con la definizione dei vari livelli software di un tipico sistema Linux.
Il kernel Linux è un programma specializzato che si avvia e funziona al livello più basso disponibile sull'hardware. Ha il compito di orchestrare tutto ciò che funziona sul computer, tra cui la gestione di eventi della tastiera, del disco e della rete per fornire fette di tempo per l'esecuzione di più programmi in parallelo.
Quando il kernel esegue un programma a livello di utente, virtualizza lo spazio di memoria in modo che i programmi credano di essere l'unico processo in esecuzione in memoria. Questa bolla protettiva di isolamento hardware e software aumenta la sicurezza e l'affidabilità. Un'applicazione non privilegiata non può accedere alla memoria appartenente ad altri programmi e, se quel programma si blocca, il kernel termina in modo che non possa danneggiare il resto del sistema.
Brezando la barriera con le chiamate di sistema Linux
Questo strato di isolamento tra applicazioni non privilegiate fornisce un limite eccellente per proteggere altre applicazioni e utenti sul sistema. Tuttavia, senza un certo modo di interfacciarsi con gli altri elementi del computer e del mondo esterno, i programmi non sarebbero in grado di realizzare molto di nulla.
Per facilitare l'interazione, il kernel designa un gate software che consente al programma di esecuzione di richiedere che il kernel agisca per suo conto. Questa interfaccia è conosciuta come una chiamata di sistema.
Poiché Linux segue la filosofia UNIX di "Everything Is A File", molte funzioni possono essere eseguite aprendo e leggendo o scrivendo in un file, che potrebbe essere un dispositivo. Su Windows, ad esempio, è possibile utilizzare una funzione chiamata CryptGenRandom per accedere ai byte casuali. Ma su Linux, questo può essere fatto semplicemente aprendo il "file"/dev/urandom e leggendo byte da esso utilizzando le chiamate di sistema di input/output standard. Questa differenza cruciale consente un'interfaccia di chiamata di sistema più semplice.
Wrapper sottile-wafer
Nella maggior parte delle applicazioni, le chiamate di sistema non vengono effettuate direttamente al kernel. Praticamente tutti i programmi si collegano nella libreria C standard, che fornisce un wrapper sottile ma importante attorno alle chiamate di sistema Linux. La libreria si assicura che gli argomenti della funzione vengano copiati nei registri del processore corretti, quindi emette la chiamata di sistema Linux corrispondente. Quando i dati vengono ricevuti dalla chiamata, il wrapper interpreta i risultati e li restituisce al programma in modo coerente.
Dietro le quinte
Ogni funzione in un programma che interagisce con il sistema viene infine tradotta in una chiamata di sistema. Per vederlo in azione, iniziamo con un esempio di base.
void main ()Questo è probabilmente il programma C più banale che tu abbia mai visto. Ottiene semplicemente il controllo tramite il punto di ingresso principale e quindi esce. Non restituisce nemmeno un valore poiché Main è definito come vuoto. Salva il file come ctest.C e compiliamiamolo:
gcc ctest.c -o ctestUna volta compilato, possiamo vedere la dimensione del file come 8664 byte. Può variare leggermente sul tuo sistema, ma dovrebbe essere circa 8k. Questo è un sacco di codice solo per entrare ed uscire! Il motivo per cui è 8k è che il runtime di Libc viene incluso. Anche se spogliamo i simboli, è ancora un po 'più di 6k.
In un esempio ancora più semplice, possiamo effettuare la chiamata del sistema Linux per uscire piuttosto che dipendere dal runtime C per farlo per noi.
void _start ()Qui ci spostiamo 1 nel registro EAX, cancella il registro EBX (che altrimenti conterrebbe il valore di restituzione), quindi chiama la chiamata di sistema Linux Interrupt 0x80 (o 128 in decimale). Questo interrupt innesca il kernel per elaborare la nostra chiamata.
Se compiliamo il nostro nuovo esempio, chiamato asmtest.C e spoglia i simboli ed escludono la libreria standard:
gcc -s -nostdlib asmtest.c -o asmtestprodurremo un binario inferiore a 1k (sul mio sistema, produce 984 byte). La maggior parte di questo codice è intestazioni eseguibili. Ora stiamo chiamando la chiamata di sistema Direct Linux.
Per tutti gli scopi pratici
In quasi tutti i casi, non dovrai mai effettuare chiamate di sistema diretta nei tuoi programmi C. Se si utilizza il linguaggio assembly, tuttavia, può sorgere la necessità. Tuttavia, in ottimizzazione, sarebbe meglio lasciare che le funzioni della libreria C effettuano le chiamate di sistema e hanno solo il codice critico per le prestazioni incorporato nelle direttive di assemblaggio.
Se si desidera visualizzare un elenco di tutte le chiamate di sistema disponibili per Linux, è possibile controllare queste pagine di riferimento: Elenco completo delle chiamate di sistema su LinuxHint.com, filippo.IO/ Linux-Sycall-table/ e o syscalls.Kernelgrok.com