Un eseguibile avrebbe bisogno di un kernel OS per funzionare?


53

So che quando viene compilato il codice sorgente, ad esempio C ++, l'output del compilatore è il codice macchina (eseguibile) che pensavo fossero istruzioni direttamente alla CPU. Recentemente stavo leggendo i kernel e ho scoperto che i programmi non possono accedere direttamente all'hardware ma devono passare attraverso il kernel.

Quindi quando compiliamo un semplice codice sorgente, diciamo con una sola printf()funzione, e la compilazione produce il codice macchina eseguibile, ciascuna istruzione in questo codice macchina verrà eseguita direttamente dalla memoria (una volta che il codice è stato caricato in memoria dal sistema operativo) o ogni comando nel codice macchina deve ancora passare attraverso il sistema operativo (kernel) per essere eseguito?

Ho letto una domanda simile . Non ha spiegato se il codice macchina che viene generato dopo la compilazione è direttamente un'istruzione per la CPU o se sarà necessario passare nuovamente attraverso il kernel per creare le istruzioni corrette per la CPU. Cioè, cosa succede dopo che il codice macchina è stato caricato in memoria? Passerà attraverso il kernel o parlerà direttamente con il processore?


29
Se stai scrivendo codice per un Arduino non hai bisogno di un sistema operativo.
Stib

12
printfnon è un grande esempio. È esplicitamente definito dalla specifica C come una funzione disponibile solo in implementazioni "ospitate" (ovvero in esecuzione su un kernel, anziché "indipendente", che potrebbe non richiederne una). E sulla maggior parte delle piattaforme, printfè solo una funzione fornita da te libcche fa un sacco di cose per tuo conto (che alla fine include una syscall da stampare su stdout). Non è davvero diverso dal chiamare libvlc_media_list_add_mediao PyObject_GetAttr, tranne per il fatto che alcune printfimplementazioni sono garantite collegabili senza l'aggiunta di ulteriori non standard -l.
abarnert,

1
Questo esiste! (non affiliato, ho pensato che fosse bello) erikyyy.de/invaders
Nonny Moose,

9
Questo dipende in realtà dalla definizione precisa dei termini "eseguibile", "kernel", "run", "need", "talk to" e "go through". Senza una definizione precisa di tali termini, la domanda è insoddisfacente.
Jörg W Mittag,

3
@ JörgWMittag - Se vuoi essere pedante, allora perché stai solo esaminando solo quei termini e solo questa domanda? Il termine veramente saliente che deve essere definito è "sistema operativo", che viene applicato in modo discutibile a MS-DOS (e ambienti di runtime a attività singola simili). Se ci sono alcune persone (male informate) che pensano che il BIOS del PC sia un sistema operativo , allora tutto è pronto? Penso di no. Il PO usa quelle parole in un contesto che sembra ragionevole (specialmente se non di madrelingua inglese) o non tecnico.
segatura

Risposte:


86

Come qualcuno che ha scritto programmi che vengono eseguiti senza un sistema operativo, offro una risposta definitiva.

Un eseguibile avrebbe bisogno di un kernel OS per funzionare?

Dipende da come è stato scritto e costruito quel programma.
È possibile scrivere un programma (supponendo di avere le conoscenze) che non richiede affatto un sistema operativo.
Tale programma è descritto come autonomo .
Caricatori di avvio e programmi diagnostici sono usi tipici per programmi autonomi.

Tuttavia, il tipico programma scritto e incorporato in alcuni ambienti del sistema operativo host sarebbe predefinito per l'esecuzione nello stesso ambiente del sistema operativo host.
Decisioni e azioni molto esplicite sono necessarie per scrivere e costruire un programma autonomo.


... l'output del compilatore è il codice macchina (eseguibile) che pensavo fossero istruzioni direttamente alla CPU.

Corretta.

Recentemente stavo leggendo i kernel e ho scoperto che i programmi non possono accedere direttamente all'hardware ma devono passare attraverso il kernel.

Questa è una limitazione imposta da una modalità CPU che il sistema operativo utilizza per eseguire i programmi e facilitata da alcuni strumenti di compilazione come compilatori e librerie.
Non è una limitazione intrinseca per ogni programma mai scritto.


Quindi quando compiliamo un semplice codice sorgente, diciamo solo con una funzione printf (), e la compilazione produce il codice macchina eseguibile, ciascuna istruzione in questo codice macchina verrà eseguita direttamente dalla memoria (una volta che il codice è stato caricato in memoria dal sistema operativo ) o ciascun comando nel codice macchina dovrà comunque passare attraverso il sistema operativo (kernel) per essere eseguito?

Ogni istruzione viene eseguita dalla CPU.
Un'istruzione non supportata o illegale (ad esempio, il processo ha privilegi insufficienti) causerà un'immediata eccezione e la CPU eseguirà invece una routine per gestire questa condizione insolita.

Una funzione printf () non deve essere utilizzata come esempio di "codice sorgente semplice" .
La traduzione da un linguaggio di programmazione di alto livello orientato agli oggetti in codice macchina potrebbe non essere banale come si suppone.
E poi scegli una delle funzioni più complesse da una libreria di runtime che esegue conversioni di dati e I / O.

Nota che la tua domanda stabilisce un ambiente con un sistema operativo (e una libreria di runtime).
Dopo l'avvio del sistema e il controllo del computer da parte del sistema operativo, vengono imposte restrizioni su ciò che un programma può fare (ad es. I / O deve essere eseguito dal sistema operativo).
Se si prevede di eseguire un programma autonomo (ovvero senza un sistema operativo), non è necessario avviare il computer per eseguire il sistema operativo.


... cosa succede dopo che il codice macchina è stato caricato in memoria?

Dipende dall'ambiente.

Per un programma autonomo, può essere eseguito, ovvero il controllo viene passato saltando all'indirizzo iniziale del programma.

Per un programma caricato dal sistema operativo, il programma deve essere collegato dinamicamente alle librerie condivise da cui dipende. Il sistema operativo deve creare uno spazio di esecuzione per il processo che eseguirà il programma.

Passerà attraverso il kernel o parlerà direttamente con il processore?

Il codice macchina viene eseguito dalla CPU.
Non "passano attraverso il kernel" , ma nemmeno "parlano con il processore" .
Il codice macchina (composto da codice operativo e operandi) è un'istruzione per la CPU che viene decodificata e l'operazione viene eseguita.

Forse il prossimo argomento che dovresti esaminare sono le modalità CPU .


2
"Se si prevede di eseguire un programma autonomo (ovvero senza un sistema operativo), non è necessario avviare il computer per eseguire il sistema operativo." non è del tutto corretto. Molti programmi DOS sono stati caricati dopo DOS e quindi hanno completamente ignorato i servizi DOS (facendo direttamente il bit-bang o forse chiamando direttamente il BIOS). Win3.x è un eccellente esempio che (tranne in alcuni casi angolari interessanti) ha ignorato la presenza di DOS. Win95 / 98 / Me ho fatto anche questo. Esistono molti esempi di sistemi operativi che supportano programmi autonomi, molti dell'era a 8/16 bit.
Eric Towers,

8
@EricTowers - Con "DOS" si intende presumibilmente MS-DOS (dal momento che ho usato DOS non correlati a MS o Intel)? Stai citando un "sistema operativo" che non corrisponde nemmeno ai criteri dei miei libri di testo universitari degli anni '70 sui concetti e sul design del sistema operativo. Le origini di MS-DOS risalgono (attraverso Seattle Computer Products) a CP / M, che non è esplicitamente chiamato un sistema operativo dal suo autore Gary Kildall. FWIW un sistema operativo che consente a un programma di assumere il controllo del sistema non è riuscito nella sua funzione di base di gestione delle risorse di sistema. "Esistono molti esempi di sistemi operativi che supportano programmi autonomi" - "Supporto" o impossibile impedirlo?
segatura,


3
Mi piace la terminologia "indipendente" di GCC. La parola inglese ha tutte le giuste connotazioni per il codice che funziona senza un sistema operativo, forse anche meglio di "standalone". ad es. puoi compilare gcc -O2 -ffreestanding my_kernel.c special_sauce.Sper creare un eseguibile che non presuma che ci siano le normali librerie o roba del sistema operativo. (Ovviamente avresti normalmente bisogno di uno script del linker per farlo utilmente collegare in un formato file che un bootloader vorrà caricare!)
Peter Cordes,

4
@PeterCordes "standalone" è il termine usato nello standard C che IMO può essere considerato in qualche modo autorevole. In alternativa, un buon termine è anche "non ospitato" (come ospitato dal sistema operativo)
Jan Dorniak,

38

Il kernel è "solo" più codice. È solo che quel codice è un livello che vive tra le parti più basse del sistema e l'hardware reale.

Tutto funziona direttamente sulla CPU, basta passare attraverso i livelli per fare qualsiasi cosa.

Il tuo programma "ha bisogno" del kernel nello stesso modo in cui ha bisogno delle librerie C standard per usare il printfcomando in primo luogo.

Il codice effettivo del programma viene eseguito sulla CPU, ma i rami che il codice fa stampare qualcosa sullo schermo passano attraverso il codice per la printffunzione C , attraverso vari altri sistemi e interpreti, ognuno dei quali esegue la propria elaborazione per capire come hello world! viene effettivamente stampato sullo schermo.

Supponi di avere un programma terminale in esecuzione su un gestore di finestre desktop, in esecuzione sul kernel che a sua volta è in esecuzione sul tuo hardware.

C'è molto di più che succede ma lascia che sia semplice ...

  1. Nel programma terminale si esegue il programma per la stampa hello world!
  2. Il terminale vede che il programma ha scritto (tramite le routine di output C) hello world!sulla console
  3. Il programma terminale arriva al gestore della finestra del desktop dicendo "Mi sono hello world!scritto su di me, puoi metterlo in posizione x, per yfavore?"
  4. Il desktop manager della finestra passa al kernel con "uno dei miei programmi vuole che il tuo dispositivo grafico metta del testo in questa posizione, arriva amico!"
  5. Il kernel trasmette la richiesta al driver del dispositivo grafico, che la formatta in modo che la scheda grafica possa essere compresa
  6. A seconda di come è collegata la scheda grafica, è necessario chiamare altri driver di dispositivo kernel per inviare i dati su bus di dispositivi fisici come PCIe, gestire cose come assicurarsi che sia selezionato il dispositivo corretto e che i dati possano passare attraverso il bridge pertinente o convertitori
  7. L'hardware visualizza roba.

Questa è un'enorme semplificazione eccessiva solo per la descrizione. Ecco i draghi.

In effetti tutto ciò che fai che richiede accesso all'hardware, che si tratti di display, blocchi di memoria, bit di file o qualcosa del genere, deve passare attraverso un driver di dispositivo nel kernel per capire esattamente come parlare con il dispositivo in questione. Che si tratti di un driver di file system in cima a un driver del controller del disco rigido SATA che si trova in cima a un dispositivo bridge PCIe.

Il kernel sa come legare insieme tutti questi dispositivi e presenta un'interfaccia relativamente semplice per i programmi per fare le cose senza dover sapere come fare tutte queste cose da soli.

I gestori di finestre desktop forniscono un livello che significa che i programmi non devono sapere come disegnare finestre e giocare bene con altri programmi che provano a visualizzare le cose contemporaneamente.

Infine, il programma terminale significa che il tuo programma non ha bisogno di sapere come disegnare una finestra, né come parlare con il driver della scheda grafica del kernel, né tutta la complessità che ha a che fare con la gestione dei buffer dello schermo e la visualizzazione dei tempi e agitando il righe di dati sul display.

È tutto gestito da livelli su livelli di codice.


Non solo l' accesso all'hardware , la maggior parte delle comunicazioni tra i programmi passa anche attraverso il kernel; ciò che in genere non coinvolge almeno il kernel sta creando un canale più diretto. Tuttavia, ai fini della domanda, è anche possibile e praticato in casi molto più semplici condensare tutto il codice in un unico programma.
Chris Stratton,

In effetti, il tuo programma terminale non deve nemmeno essere in esecuzione sullo stesso computer del programma che sta scrivendo cose su di esso.
jamesqf,

Dato che potrebbe essere necessario dichiararlo esplicitamente in questa domanda, tieni presente che quando parliamo di programmi che "parlano l'uno con l'altro", è metaforico.
user253751

21

Dipende dall'ambiente. In molti computer più vecchi (e più semplici!), Come IBM 1401, la risposta sarebbe "no". Il compilatore e il linker hanno emesso un "binario" autonomo che è stato eseguito senza alcun sistema operativo. Quando il programma ha smesso di funzionare, ne hai caricato uno diverso, che funzionava anche senza sistema operativo.

Un sistema operativo è necessario in ambienti moderni perché non si esegue solo un programma alla volta. La condivisione dei core della CPU, della RAM, del dispositivo di archiviazione di massa, della tastiera, del mouse e del display, tra più programmi contemporaneamente richiede il coordinamento. Il sistema operativo lo fornisce. Quindi in un ambiente moderno il tuo programma non può semplicemente leggere e scrivere il disco o l'SSD, ma deve chiedere al sistema operativo di farlo per suo conto. Il sistema operativo riceve tali richieste da tutti i programmi che desiderano accedere al dispositivo di archiviazione, implementa cose come i controlli di accesso (non può consentire agli utenti ordinari di scrivere sui file del sistema operativo), li mette in coda sul dispositivo e ordina le informazioni restituite ai programmi (processi) corretti.

Inoltre, i computer moderni (a differenza, diciamo, del 1401) supportano la connessione di una vasta gamma di dispositivi I / O, non solo quelli che IBM ti venderebbe ai vecchi tempi. Il tuo compilatore e linker non possono assolutamente conoscere tutte le possibilità. Ad esempio, la tastiera potrebbe essere interfacciata tramite PS / 2 o USB. Il sistema operativo consente di installare "driver di dispositivo" specifici del dispositivo che sanno come comunicare con tali dispositivi, ma presentano un'interfaccia comune per la classe di dispositivi al sistema operativo. Quindi il tuo programma e persino il sistema operativo non devono fare nulla di diverso per ottenere sequenze di tasti da una tastiera USB vs una tastiera PS / 2 o per accedere, diciamo, a un disco SATA locale vs un dispositivo di archiviazione USB vs spazio di archiviazione da qualche parte su un NAS o SAN. Tali dettagli sono gestiti dai driver di dispositivo per i vari controller di dispositivo.

Per i dispositivi di archiviazione di massa, il sistema operativo fornisce a tutti quelli un driver di file system che presenta la stessa interfaccia a directory e file indipendentemente da dove e come viene implementata la memoria. E ancora, il sistema operativo si preoccupa dei controlli di accesso e della serializzazione. In generale, ad esempio, lo stesso file non dovrebbe essere aperto per la scrittura da più di un programma alla volta senza saltare attraverso alcuni cerchi (ma le letture simultanee sono generalmente ok).

Quindi, in un moderno ambiente di uso generale, sì, hai davvero bisogno di un sistema operativo. Ma anche oggi ci sono computer come controller in tempo reale che non sono abbastanza complicati da averne bisogno.

Nell'ambiente Arduino, ad esempio, non esiste davvero un sistema operativo. Certo, c'è un sacco di codice di libreria che l'ambiente di compilazione incorpora in ogni "binario" che costruisce. Ma poiché non esiste alcuna persistenza di quel codice da un programma all'altro, non è un sistema operativo.


10

Penso che molte risposte fraintendano la domanda, che si riduce a questo:

Un compilatore genera il codice macchina. Questo codice macchina è eseguito direttamente da una CPU o è "interpretato" dal kernel?

Fondamentalmente, la CPU esegue direttamente il codice macchina . Sarebbe molto più lento far eseguire tutte le applicazioni al kernel. Tuttavia, ci sono alcuni avvertimenti.

  1. Quando è presente un sistema operativo, in genere i programmi applicativi non possono eseguire determinate istruzioni o accedere a determinate risorse. Ad esempio, se un'applicazione esegue un'istruzione che modifica la tabella di interrupt di sistema, la CPU passerà invece a un gestore di eccezioni del sistema operativo in modo che l'applicazione offensiva venga chiusa. Inoltre, alle applicazioni di solito non è consentito leggere / scrivere nella memoria del dispositivo. (Vale a dire "parlare con l'hardware".) Accedere a queste aree di memoria speciali è il modo in cui il sistema operativo comunica con dispositivi come la scheda grafica, l'interfaccia di rete, l'orologio di sistema, ecc.

  2. Le restrizioni che un sistema operativo pone alle applicazioni sono raggiunte da funzioni speciali della CPU, come modalità privilegi, protezione della memoria e interruzioni. Sebbene qualsiasi CPU che potresti trovare in uno smartphone o in un PC abbia queste caratteristiche, alcune CPU no. Queste CPU hanno effettivamente bisogno di kernel speciali che "interpretano" il codice dell'applicazione per ottenere le funzionalità desiderate. Un esempio molto interessante è il Gigatron , che è un computer con 8 istruzioni che puoi costruire con chip che emula un computer con 34 istruzioni.

  3. Alcuni linguaggi come Java "compilano" in qualcosa chiamato Bytecode, che in realtà non è un codice macchina. Anche se in passato venivano interpretati per eseguire i programmi, in questi giorni viene generalmente utilizzato qualcosa chiamato compilazione Just-in-Time, quindi finiscono per essere eseguiti direttamente sulla CPU come codice macchina.

  4. L'esecuzione del software in una macchina virtuale richiedeva che il suo codice macchina fosse "interpretato" da un programma chiamato Hypervisor . A causa dell'enorme richiesta del settore per le macchine virtuali, i produttori di CPU hanno aggiunto funzionalità come VTx alle loro CPU per consentire la maggior parte delle istruzioni di un sistema guest da eseguire direttamente dalla CPU. Tuttavia, durante l'esecuzione di software progettato per un incompatibili CPU in una macchina virtuale (ad esempio, l'emulazione di un NES), il codice macchina avrà bisogno di essere interpretati.


1
Sebbene il bytecode di Java non sia normalmente il codice macchina, esistono ancora processori Java .
Ruslan,

Gli hypervisor non sono sempre stati interpreti. L'interpretazione è ovviamente necessaria se la macchina virtuale come set di istruzioni incompatibile con il suo host, ma per l'esecuzione sulla stessa architettura, anche i primi hypervisor eseguono il codice direttamente sulla CPU (potresti essere confuso dalla necessità di kernel paravirtualizzati, per CPU senza il necessario supporto hypervisor).
Toby Speight,

5

Quando compili il tuo codice, crei il cosiddetto codice "oggetto" che (nella maggior parte dei casi) dipende dalle librerie di sistema ( printfad esempio), quindi il tuo codice viene racchiuso da un linker che aggiungerà un tipo di caricatore di programmi che il tuo particolare sistema operativo può riconoscere (ecco perché non è possibile eseguire il programma compilato per Windows su Linux per esempio) e sapere come decomprimere il codice ed eseguire. Quindi il tuo programma è come una carne all'interno di un panino e può essere consumato solo in bundle, nel suo insieme.

Recentemente ho letto su Kernels e ho scoperto che i programmi non possono accedere direttamente all'hardware ma devono passare attraverso il kernel.

Bene è a metà strada vero; se il tuo programma è un driver in modalità kernel, in realtà puoi accedere direttamente all'hardware se sai come "parlare" con l'hardware, ma di solito (specialmente per hardware non documentato o complicato) le persone usano driver che sono librerie del kernel. In questo modo puoi trovare funzioni API che sanno come parlare con l'hardware in modo quasi leggibile dall'uomo senza la necessità di conoscere indirizzi, registri, tempistiche e molte altre cose.

ciascuna istruzione in questo codice macchina verrà eseguita direttamente dalla memoria (una volta che il codice è stato caricato nella memoria dal sistema operativo) o ogni comando nel codice macchina dovrà comunque passare attraverso il sistema operativo (kernel) per essere eseguito

Bene, il kernel è una cameriera, la cui responsabilità è accompagnarti a un tavolo e servirti. L'unica cosa che non può fare - è mangiare per te, dovresti farlo da solo. Lo stesso con il tuo codice, il kernel decomprimerà il tuo programma in una memoria e avvierà il tuo codice che è il codice macchina eseguito direttamente dalla CPU. Un kernel deve solo supervisionarti: cosa ti è permesso e cosa non ti è permesso fare.

non spiega se il codice macchina che viene generato dopo la compilazione è un'istruzione direttamente alla CPU o dovrà passare nuovamente attraverso il kernel per creare le istruzioni corrette per la CPU?

Il codice macchina generato dopo la compilazione è direttamente un'istruzione per la CPU. Non ci sono dubbi. L'unica cosa che devi tenere a mente, non tutto il codice nel file compilato è il codice macchina / CPU effettivo. Linker ha avvolto il tuo programma con alcuni metadati che solo il kernel può interpretare, come un indizio - cosa fare del tuo programma.

Cosa succede dopo che il codice macchina è stato caricato nella memoria? Passerà attraverso il kernel o parlerà direttamente con il processore.

Se il tuo codice è un semplice codice operativo come l'aggiunta di due registri, verrà eseguito direttamente dalla CPU senza l'assistenza del kernel, ma se il tuo codice utilizza le funzioni delle librerie, tali chiamate saranno assistite dal kernel, come nell'esempio con la cameriera, se vuoi mangiare in un ristorante ti darebbe uno strumento - forchetta, cucchiaio (e ancora le loro risorse) ma cosa ne farai, - fino al tuo "codice".

Bene, solo per evitare la fiamma nei commenti - è davvero un modello semplificato che spero possa aiutare OP a capire le cose di base, ma sono ben accetti buoni suggerimenti per migliorare questa risposta.


3

Quindi quando compiliamo un semplice codice sorgente, diciamo solo con una funzione printf (), e la compilazione produce il codice macchina eseguibile, ciascuna istruzione in questo codice macchina verrà eseguita direttamente dalla memoria (una volta che il codice è stato caricato nella memoria dal sistema operativo) o ogni comando nel codice macchina dovrà comunque passare attraverso il sistema operativo (kernel) per essere eseguito?

In sostanza, solo le chiamate di sistema vanno al kernel. Qualunque cosa abbia a che fare con l'I / O o l'allocazione / deallocazione della memoria alla fine provoca una chiamata di sistema. Alcune istruzioni possono essere eseguite solo in modalità kernel e causeranno un'eccezione alla CPU. Le eccezioni causano il passaggio alla modalità kernel e un salto al codice kernel.

Il kernel non elabora tutte le istruzioni in un programma. Fa solo il sistema chiama e passa tra i programmi in esecuzione per condividere la CPU.

Non è possibile eseguire l'allocazione di memoria in modalità utente (senza il kernel), se si accede alla memoria non si dispone dell'autorizzazione per accedere, la MMU, precedentemente programmata dal kernel, rileva e provoca un'eccezione di "errore di segmentazione" a livello di CPU , che attiva il kernel e il kernel uccide il programma.

Non è possibile eseguire I / O in modalità utente (senza kernel), se si accede a porte I / O o registri per dispositivi o indirizzi collegati a dispositivi (uno o entrambi necessari per eseguire qualsiasi I / O), questi attivano un eccezione allo stesso modo.


Un eseguibile avrebbe bisogno di un kernel OS per funzionare?

Dipende dal tipo di eseguibile.

I kernel, oltre a mediare l'accesso condiviso a RAM e hardware, svolgono anche una funzione di caricamento.

Molti "formati eseguibili", come ELF o PE, hanno metadati nel file eseguibile oltre al codice, ed è compito del caricatore elaborarlo. Leggi i dettagli cruenti sul formato PE di Microsoft per ulteriori informazioni.

Questi eseguibili fanno anche riferimento a librerie ( file di .dlloggetti condivisi Windows o Linux .so) - il loro codice deve essere incluso.

Se il compilatore produce un file che deve essere elaborato da un caricatore del sistema operativo e tale caricatore non è presente, non funzionerà.

  • Puoi includere il codice che svolge il lavoro del caricatore?

Sicuro. Devi convincere il sistema operativo a eseguire in qualche modo il tuo codice raw senza elaborare metadati. Se il tuo codice chiama API del kernel, non funzionerà comunque.

  • Cosa succede se non chiama API del kernel?

Se in qualche modo questo file eseguibile viene caricato da un sistema operativo (ovvero se consente il caricamento e l'esecuzione di codice raw), sarà comunque in modalità utente. Se il tuo codice accede a cose proibite in modalità utente, a differenza della modalità kernel, come la memoria non allocata o gli indirizzi / i registri dei dispositivi I / O, andrà in crash con privilegi o violazioni del segmento (di nuovo, le eccezioni passano alla modalità kernel e vengono gestite lì) e ancora non funzionerà.

  • E se lo avessi eseguito dalla modalità kernel.

Quindi funzionerà.



Questo non è del tutto corretto. Il requisito che l'accesso all'hardware passare attraverso il kernel, o che ci anche essere un kernel, è una decisione design made in senso affermativo su molti sistemi di oggi, ma anche fatto in senso negativo (fino ad oggi) su molti sistemi semplici.
Chris Stratton,

Sto spiegando come vanno le cose se A) c'è un kernel e B) se stai eseguendo il codice su una CPU con modalità utente / supervisore e una MMU per aiutarti a farlo. Sì, ci sono CPU e microcontrollori senza MMU o modalità utente / supervisore, e sì alcuni sistemi funzionano senza utilizzare l'intera infrastruttura utente / supervisore. La prima Xbox di Microsoft è stata così - anche se una CPU x86 standard con modalità utente / supervisore, da quello che ho capito non ha mai lasciato la modalità kernel - il gioco caricato poteva fare quello che voleva.
LawrenceC,

1
Il sistema Macintosh, prima di MacOS X, era un sistema operativo di un computer per uso generale , in esecuzione su CPU per uso generale (famiglia 68000, PowerPC) con supporto per la protezione della memoria per decenni (tranne i primi computer basati su 68000 credo) che non ha mai usato la protezione della memoria : qualsiasi programma potrebbe accedere a qualsiasi cosa in memoria.
curiousguy,

3

TL; DR n.

Lo sviluppo di Arduino viene in mente come un ambiente attuale in cui non esiste un sistema operativo. Fidati di me, su uno di questi bambini non hai lo spazio per un sistema operativo.

Allo stesso modo, i giochi per Sega Genesis non avevano un sistema operativo fornito da Sega a cui rivolgersi. Hai appena realizzato il tuo gioco in un assemblatore 68K, scrivendo direttamente sul metallo nudo.

O dove mi sono tagliato i denti, facendo un lavoro integrato sull'Intel 8051. Ancora una volta quando tutto ciò che hai è una eprom 2716 con un ingombro 2k * 8, non hai spazio per un sistema operativo.

Naturalmente, ciò presuppone un uso molto ampio della parola application. Come domanda retorica, vale la pena chiedersi se uno schizzo di Arduino è effettivamente un'applicazione.


3

Anche se non voglio implicare che le altre risposte non siano giuste da sole, forniscono troppi dettagli che, temo, sono ancora molto oscuri per te.

La risposta di base è che il codice verrà eseguito direttamente sul processore. E no, il codice macchina non "parlerà" con nessuno, è il contrario. Il processore è il componente attivo e tutto ciò che fai nel tuo computer sarà fatto da quel processore (sto semplificando un po 'le cose qui, ma per ora va bene). Il processore leggerà il codice, lo eseguirà e sputerà i risultati, il codice macchina è solo cibo per il processore.

La tua confusione deriva dall'uso della parola hardware. Sebbene la divisione non sia così chiara come una volta, è meglio se si pensa in termini di periferiche piuttosto che chiamare semplicemente tutto l'hardware. Quindi, se sul tuo computer è presente un sistema operativo o simile, il tuo programma deve utilizzare i suoi servizi per accedere alle periferiche ma il processore stesso non è una periferica, è l'unità di elaborazione principale su cui il tuo programma viene eseguito direttamente.

I kernel, i sistemi operativi e i livelli intermedi simili vengono generalmente utilizzati solo nei sistemi più grandi in cui ci si aspetta che vengano eseguiti diversi programmi ed è necessario che il sistema gestisca il modo in cui questi programmi possono utilizzare le periferiche del computer (abbastanza spesso contemporaneamente). In questi casi, i programmi in esecuzione possono accedere a queste periferiche solo tramite il sistema che deciderà come condividerle e si assicurerà che non vi siano conflitti. Piccoli sistemi in cui non è necessaria alcuna gestione tra i programmi concorrenti perché non ce ne sono, spesso non hanno alcun sistema sottostante e il singolo programma normalmente in esecuzione su questi sistemi è più o meno libero di fare ciò che vuole con le periferiche.


2

Il BIOS che viene eseguito sul computer all'accensione è un codice eseguibile memorizzato nella ROM. Consiste in istruzioni macchina più dati. Esiste un compilatore (o assemblatore) che assembla questo BIOS dal codice sorgente. Questo è un caso speciale.

Altri casi speciali includono il programma bootstrap che carica il kernel e il kernel stesso. Questi casi speciali sono generalmente codificati in un linguaggio diverso dal C ++.

Nel caso generale, è molto più pratico che il compilatore produca alcune istruzioni che invocano i servizi di sistema forniti da un kernel o dalle routine di libreria. Rende il compilatore molto più leggero. Inoltre, rende il codice compilato più leggero.

All'altra estremità dello spettro è Java. In Java, il compilatore non traduce il codice sorgente in istruzioni della macchina, poiché questo termine è generalmente compreso. Al contrario, il codice sorgente viene tradotto in "istruzioni macchina" per una macchina immaginaria, chiamata Java Virtual Machine. Prima che un programma Java possa essere eseguito, deve essere combinato con il runtime Java, che include un interprete per la Java Virtual Machine.


2

Ai vecchi tempi il tuo programma era responsabile di fare tutto ciò che doveva essere fatto durante l'esecuzione del tuo programma, o da te stesso o aggiungendo il codice della libreria che altri hanno scritto nel tuo programma. L'unica cosa che correva accanto a quello nel computer era il codice da leggere nel tuo programma compilato - se sei stato fortunato. Alcuni computer dovevano inserire il codice tramite switch prima di poter fare di più (il processo originale "bootstrap"), o anche l'intero programma è entrato in questo modo.

Si è rapidamente scoperto che era bello avere un codice in esecuzione in grado di caricare ed eseguire il programma. In seguito è stato scoperto che i computer erano abbastanza potenti da supportare l'esecuzione di più programmi contemporaneamente avendo il passaggio della CPU tra di loro, soprattutto se l'hardware poteva aiutare, ma con l'ulteriore complessità dei programmi non fare passi l'uno sull'altro (ad esempio , come gestire più programmi cercando di inviare dati alla stampante contemporaneamente?).

Tutto ciò ha comportato lo spostamento di una grande quantità di codice helper dai singoli programmi al "sistema operativo", con un modo standardizzato di invocare il codice helper dai programmi utente.

Ed è qui che siamo oggi. I tuoi programmi funzionano a tutta velocità ma ogni volta che hanno bisogno di qualcosa gestito dal sistema operativo, chiamano routine di supporto fornite dal sistema operativo e quel codice non è necessario e non è presente nei programmi utente stessi. Ciò includeva la scrittura sul display, il salvataggio di file, l'accesso alla rete, ecc.

Sono stati scritti micro kernel che forniscono esattamente ciò che è necessario per un determinato programma per funzionare senza un sistema operativo completo. Questo ha alcuni vantaggi per gli utenti esperti, regalando la maggior parte degli altri. Potresti voler leggere la pagina di Wikipedia al riguardo - https://en.wikipedia.org/wiki/Microkernel - se vuoi saperne di più.

Ho sperimentato un microkernel in grado di eseguire una Java Virtual Machine, ma in seguito ho scoperto che il punto debole per questo è Docker.


1

Nei tipici sistemi operativi desktop, il kernel stesso è un eseguibile. (Windows ha ntoskrnl.exe; Linux ha vmlinux, ecc.) Se fosse necessario un kernel per l'esecuzione di un eseguibile, tali sistemi operativi non potrebbero esistere.

Ciò di cui hai bisogno di un kernel è fare le cose che fa un kernel. Consenti a più eseguibili di eseguire contemporaneamente, arbitrare tra loro, sottrarre l'hardware, ecc. La maggior parte dei programmi non sono in grado di fare queste cose da soli con competenza, e non vorresti che lo facessero anche se potessero. Ai tempi di DOS - che a malapena si poteva definire un sistema operativo stesso - i giochi usavano spesso il sistema operativo come poco più di un caricatore e accedevano direttamente all'hardware come farebbe un kernel. Ma spesso dovevi sapere quali marchi e modelli di hardware erano nella tua macchina prima di acquistare un gioco. Molti giochi supportavano solo alcune famiglie di schede video e audio e funzionavano molto male con marchi concorrenti se funzionavano affatto. Quello'

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.