Porting di Linux su requisiti di un'altra piattaforma [chiuso]


28

So che Linux è disponibile ed è stato portato su molte piattaforme diverse come X86, ARM, PowerPC ecc.

Tuttavia, in termini di porting, cosa è richiesto esattamente?

La mia comprensione è che Linux è un software scritto in C. Pertanto, quando si esegue il porting di Linux originariamente da X86 a ARM o altri, ad esempio, non si tratta solo di ricompilare il codice con il compilatore per l'architettura di destinazione specifica?

Mettendo da parte i driver di dispositivo per diverse periferiche, cos'altro dovrebbe essere fatto quando si esegue il porting di Linux su una nuova architettura. Il compilatore non si occupa di tutto per noi?


11
Possiamo supporre che tu abbia esaminato i sorgenti del kernel specifici dell'architettura? git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/…
Kusalananda

Risposte:


57

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.


7
Scrittura molto bella! La variazione del numero di syscalls è principalmente legata alla storia: le nuove porte includono le syscalls valide al momento del porto, non si preoccupano del bagaglio storico presente nei porti più vecchi, quindi le syscall deprecate in genere non sono presenti nei porti più recente della deprecazione. (Questo non copre tutti gli scenari ...)
Stephen Kitt,

10

Oltre al porting del kernel Linux, sarà necessario definire l' interfaccia binaria dell'applicazione (ABI) per i programmi "spazio utente" e trasferire gli strati più bassi dello stack software dello spazio utente. Linux viene in genere utilizzato con componenti di spazio utente di basso livello del progetto GNU, di cui i più critici sono:

  • Il compilatore, l'assemblatore e il linker C: GCC e GNU Binutils . Per un'architettura CPU completamente nuova, è necessario eseguire il porting di questo software prima ancora di iniziare il porting del kernel, poiché il kernel è esso stesso un programma C e deve essere compilato. Se esiste già un supporto "back-end" per la CPU della tua piattaforma, ma non con Linux come kernel del sistema operativo, hai sostanzialmente meno lavoro da fare e potresti riuscire a rimandare la maggior parte del lavoro fino a quando il kernel non è attivo e in esecuzione.
  • La libreria di runtime C: " GNU libc ". Questa libreria include il codice che effettua le chiamate di sistema e interagisce in altro modo direttamente con il kernel.
  • La libreria " Foreign Function Interface", libffi , che è un componente essenziale di molti interpreti di linguaggio di alto livello, ed esegue una delle poche attività rimanenti che richiede una piccola quantità di linguaggio assembly scritto a mano.

Molti altri software hanno componenti opzionali dipendenti dalla piattaforma; ad esempio, la navigazione sul Web sarà notevolmente più veloce se si scrivono primitive crittografiche ottimizzate a mano per NSS e OpenSSL per la nuova architettura della CPU e back-end di compilazione just-in-time per IonMonkey e V8 . Ma questi non sono essenziali per far apparire una nuova piattaforma.


1

Devi dire al kernel dell'hardware su cui stai eseguendo il porting. Il compito del kernel è di interfacciarsi direttamente con l'hardware, quindi per funzionare correttamente, il kernel deve conoscere CPU, oscillatori (clock) e qualsiasi periferica, come i vari tipi di porte seriali (SPI, CAN, I2C, ecc.).

Ai vecchi tempi, lo avresti fatto scrivendo un codice specifico della piattaforma che i driver avrebbero usato per funzionare. In questi giorni, questo viene fatto scrivendo una definizione dell'albero dei dispositivi .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.