Anche se la maggior parte del codice nel kernel Linux è scritto in C, ci sono ancora molte parti di quel codice che sono molto specifiche della piattaforma in cui è in esecuzione e devono tenerne conto.
Un esempio particolare di ciò è la memoria virtuale, che funziona in modo simile sulla maggior parte delle architetture (gerarchia delle tabelle di pagine) ma ha dettagli specifici per ciascuna architettura (come il numero di livelli in ciascuna architettura, e questo è aumentato anche su x86 con introduzione di nuovi chip più grandi.) Il codice del kernel Linux introduce le macro per gestire l'attraversamento di queste gerarchie che possono essere eluse dal compilatore su architetture che hanno meno livelli di tabelle di pagine (in modo che il codice sia scritto in C, ma contenga i dettagli dell'architettura in considerazione.)
Molte altre aree sono molto specifiche per ciascuna architettura e devono essere gestite con un codice specifico dell'arco. Tuttavia, la maggior parte di questi riguarda il codice nel linguaggio assembly. Esempi sono:
Cambio di contesto : il cambio di contesto comporta il salvataggio del valore di tutti i registri per il processo che viene commutato e il ripristino dei registri dall'insieme salvato del processo pianificato nella CPU. Anche il numero e l'insieme dei registri è molto specifico per ciascuna architettura. Questo codice viene in genere implementato in assembly, per consentire l'accesso completo ai registri e anche per assicurarsi che funzioni il più velocemente possibile, poiché le prestazioni del cambio di contesto possono essere fondamentali per il sistema.
Chiamate di sistema : il meccanismo mediante il quale il codice spazio utente può attivare una chiamata di sistema è in genere specifico dell'architettura (e talvolta anche del modello specifico di CPU, ad esempio Intel e AMD hanno introdotto istruzioni diverse a tale scopo, le CPU meno recenti potrebbero non avere tali istruzioni, quindi i dettagli per quelli sarà ancora unico.)
Gestori di interrupt : i dettagli su come gestire gli interrupt (interrupt di processo) sono in genere specifici della piattaforma e di solito richiedono una colla a livello di assemblaggio per gestire le convenzioni di chiamata specifiche in uso per la piattaforma. Inoltre, le primitive per abilitare / disabilitare gli interrupt sono generalmente specifiche della piattaforma e richiedono anche il codice assembly.
Inizializzazione : i dettagli su come dovrebbe avvenire l'inizializzazione di solito includono anche dettagli specifici della piattaforma e spesso richiedono un codice assembly per gestire il punto di ingresso al kernel. Sulle piattaforme che dispongono di più CPU (SMP), i dettagli su come portare altre CPU online sono in genere specifici della piattaforma.
Primitive di blocco : l'implementazione di primitivi di blocco (come gli spinlock) di solito implica anche dettagli specifici della piattaforma, poiché alcune architetture forniscono (o preferiscono) diverse istruzioni della CPU per implementarle in modo efficiente. Alcuni implementeranno operazioni atomiche, altri forniranno un cmpxchg che può testare / aggiornare atomicamente (ma fallire se un altro scrittore entra per primo), altri includeranno un modificatore "lock" alle istruzioni della CPU. Ciò implica spesso anche la scrittura di codice assembly.
Probabilmente ci sono altre aree in cui è necessario un codice specifico della piattaforma o dell'architettura in un kernel (o, nello specifico, nel kernel Linux.) Guardando l'albero dei sorgenti del kernel, ci sono sottotitoli specifici dell'architettura sotto arch/
e sotto include/arch/
dove puoi trovare di più esempi di questo.
Alcuni sono in realtà sorprendenti, ad esempio vedrai che il numero di chiamate di sistema disponibili su ciascuna architettura è distinto e che alcune chiamate di sistema esisteranno in alcune architetture e non in altre. (Anche su x86, l'elenco di syscalls differisce tra un kernel a 32 e un 64 bit.)
In breve, ci sono molti casi in cui un kernel deve essere consapevole che sono specifici di una piattaforma. Il kernel Linux cerca di astrarre la maggior parte di quelli, quindi gli algoritmi di livello superiore (come il funzionamento della gestione della memoria e della pianificazione) possono essere implementati in C e funzionare allo stesso modo (o quasi lo stesso) su tutte le architetture.