È possibile scrivere un sistema operativo in C? [chiuso]

7

Qualche tempo fa ho visto un commento su una domanda Stack Overflow che mi ha sorpreso:

No one can write an operating system in C. It is not possible. What one can do is write an operating system in a C-based/C-like language that adds/defines a considerable amount of non-standard capabilities on top of C core.

È utile definire C in modo così ristretto? La gente dice che Linux, o un driver GPU, o un sistema embedded è stato "scritto in C", non "scritto in C-con-alcuni-estensioni-per-ospitare-l'-hardware".

È sbagliato farlo?

    
posta Crashworks 28.08.2013 - 00:18
fonte

5 risposte

11

Se si consente la possibilità di utilizzare i driver di dispositivo (dotati di un'interfaccia C) per comunicare con l'hardware, non c'è motivo per cui non si possa scrivere un SO in ANSI C. Tutto ciò di cui si potrebbe aver bisogno (come il puntatore nudo) che non è presente in ANSI C potrebbe essere fornito dal driver del dispositivo.

Penso che lo scrittore di quel commento sia pedante per fare un punto. Sta dicendo che non è possibile catturare tutte le possibili cose che potrebbe essere necessario fare in un sistema operativo nel linguaggio ANSI C. Non sono sicuro di essere d'accordo; ANSI C è un linguaggio completo di Turing e ha molti costrutti di basso livello che includono il bit twiddling.

In ogni caso, lo hai citato fuori dal contesto. Guarda uno dei commenti aggiuntivi più in basso nella discussione:

...you're making it sound more drastic than it is. A small amount of assembly language (inline or in separate files) and a good linker are really all you need on most architectures. Other non-standard stuff that kernels use (like fiddling with output sections, packing, alignment, branch-prediction hints, crazy pointer arithmetic, undefined union behaviour) is for optimisation.

    
risposta data 28.08.2013 - 00:54
fonte
11

La domanda è abbastanza ampia e così com'è la risposta è sì. In effetti, la risposta è sì per la maggior parte dei linguaggi di programmazione, ma c'è un catch .

Devi tradurre il tuo codice OS in qualcosa che la macchina capisca. Ed è la macchina e la sua lingua madre e la tua capacità di tradurre dalla "tua" lingua alla lingua "nativa" che determinerebbe se puoi scrivere un sistema operativo nella tua lingua o meno.

Teoria generale

Diciamo che una macchina ha una leva. E sono possibili solo due cose: quando la leva viene spinta verso il basso, la macchina verserà il caffè e, una volta tirata, la macchina smetterà di versare il caffè. Ora immagina che il mio traduttore madrelingua sia un umano che può leggere il codice C stampato su un foglio e decidere se spingere la leva in alto o in basso. Quindi, ad esempio, leggendo la riga seguente il nostro "compilatore-linker" umano spingerà la leva verso il basso.

printf("pour coffee"); //Support more similar syntax in later versions!

E leggendo la seguente riga il nostro "compilatore-linker" umano tirerà la leva verso l'alto.

printf("stop pouring coffee"); //Support more similar syntax in later versions!

Abbiamo scritto con successo un sistema operativo per questa macchina da caffè interamente in C. Se è per questo, possiamo addestrare il nostro compilatore a tradurre Java, C #, KSH, Perl, inglese, slavok, sanscrito ecc ... e "gestiscono" la macchina. Da qui il termine, Sistema operativo.

Naturalmente molti computer moderni sono in grado di fare qualcosa di più complesso di questo. E quindi la complessità del loro set di istruzioni va oltre una semplice leva stato . Questi insiemi di istruzioni alla fine metteranno solo alcuni transistor / magneti / LED ecc. In qualche stato e noi umani lo interpreteremo come risultato.

Il problema quindi diventa quello di manipolare questa macchina per raggiungere gli stati che vogliamo. E se la tua lingua (ad esempio, C) può essere tradotta in quell'insieme di istruzioni native e se puoi usare questo bridge per fare in modo che la macchina faccia ciò che vuoi, allora avrai un sistema operativo di successo.

Esempio concreto

In questo momento sto utilizzando un sistema x86_64. Questo sistema non sa cosa sia C. Non sa cosa siano OS X, Windows o BSD. Alla fine sta eseguendo un codice assembly x86_64. Quel codice non è stato scritto dagli umani (per la maggior parte). Probabilmente è stato scritto da umani in C o C ++ e tradotto nel linguaggio assembly. Se copio questo codice compilato sulla mia macchina Power PC, non funzionerà. Ho bisogno del codice originale C / C ++ / whatever_language e ho bisogno di tradurre quel codice nella lingua del PC. Se sto provando qualcosa in C che non è traducibile per alimentare il linguaggio PC, quella funzione non funzionerà sul nuovo sistema operativo.

E i dispositivi?

Più dispositivi inserisci nella macchina (ad esempio un monitor, un mouse, una stampante, un'uscita audio, ecc.) più codice dovrai scrivere per i bridge. Questo è ciò che fanno i piloti. Puoi scrivere un driver in C se vuoi. Tutto ciò che serve è un modo per tradurre C nel "set di istruzioni" di quel dispositivo. Di solito, è più semplice incorporare del codice / circuito nel dispositivo che legge segnali elettrici standard e ingannare il core computer per generare quei segnali elettrici usando il set di istruzioni standard e i bus del dispositivo (ad esempio, USB).

Che cos'è il bootstrap?

Ora, naturalmente, il sistema operativo in questi giorni "spedisce" con la macchina. E ciò che le persone fanno è installare il codice [compilato nella lingua dell'insieme delle istruzioni della macchina] in un punto in cui la macchina può trovarlo da solo. Il trucco è solo quello di riavviare la macchina per trovare quel codice quando lo si avvia. Di seguito è riportato un JVM esempio di bootstrap:

public final class Hello {
    public static void main(String[] args_) {
        System.out.println("Hello, World!");
    }
}

0000: cafe babe 0000 002e 001a 0a00 0600 0c09  ................

Che dire ...?

Vedi Tanenbaum o poni un'altra domanda.

    
risposta data 31.08.2013 - 04:43
fonte
5

Is it incorrect to do so?

Non è "errato" definire C in questo modo ... in un contesto particolare.

My intention isn't to snipe at a particular commenter, but to suss out the boundaries of when one can say "X was written in C" and when you really need to say "X was written in a C-like language."

Si può dire ciò che piace! Non ci sono leggi di terminologia IT che dicono cosa significano le parole.

Il ragazzo sta facendo un punto (un po 'pedante) equiparando "C" con il linguaggio che è rigorosamente definito dagli standard ANSI C. Ma va bene. sappiamo cosa intende .

E il lato ribalta è che il resto di noi può usare "C" per indicare le implementazioni pratiche del linguaggio C ... se vogliamo.

    
risposta data 28.08.2013 - 03:15
fonte
3

Penso che chiunque abbia scritto quel commento non sappia di cosa sta parlando perché il motivo alla base della creazione di C è stato quello di scrivere UNIX (UNO dei migliori sistemi operativi di tutti i tempi). Non sto dicendo che sia la lingua migliore per scrivere un sistema operativo con perché molte cose sono cambiate da allora (e credetemi quando dico molto) e ora ci sono molte lingue che sono migliori di C quando si tratta di scrivere un sistema operativo, ma è tutt'altro che impossibile scrivere un Sistema operativo con C.

    
risposta data 31.08.2013 - 03:26
fonte
2

C'è un grosso problema con la scrittura di un puramente in un linguaggio di alto livello: nessun linguaggio di alto livello esistente ti consente di accedere a tutte le istruzioni della CPU che un sistema operativo deve utilizzare.

Prendiamo ad esempio l'architettura X86: implementa la memoria virtuale fornendo un singolo registro per scopi speciali che punta a un albero di tabelle di pagine. Ora, un kernel che deve impostare lo spazio degli indirizzi virtuali per un processo deve fare due cose: 1. costruire l'albero delle tabelle delle pagine e 2. caricare un puntatore alla radice di quell'albero nel registro delle funzioni speciali. Tuttavia, quel registro di scopo speciale è inaccessibile da C . Il passaggio 1 può essere eseguito in C, il passaggio 2 no. - L'insieme di istruzioni che possono uscire da un compilatore C è un vero sottoinsieme delle istruzioni della CPU disponibili, e tale sottoinsieme manca di tutte quelle istruzioni per scopi speciali che sono richieste per manipolare la modalità di elaborazione della CPU stessa.

Ecco perché ogni kernel esistente deve includere una certa quantità di codice assembler. Naturalmente, i programmatori del kernel cercano di mantenere la quantità di codice assembler più bassa possibile, scrivendo la maggior parte del kernel in un linguaggio di alto livello come C. Questa massa di codice è la ragione per cui la gente dice "Linux è scritto in C", perché il 99% del kernel Linux è in effetti un codice C. Ma C da solo non può fare il trucco.

    
risposta data 09.12.2015 - 10:48
fonte

Leggi altre domande sui tag