Come fa un programma a fare una chiamata di sistema

3

Sto leggendo i sistemi operativi moderni di Tanenbaum e non riesco davvero a cogliere il seguente concetto: come fa un programma a fare una chiamata di sistema? Voglio dire, ho le nozioni di base (correggimi se sbaglio): il SO è solo un altro programma in esecuzione sulla macchina (la differenza è che può essere eseguito in modalità kernel avendo accesso completo all'hardware della macchina) e quando il programma di un utente desidera avere una sorta di funzionalità avanzata fornita dal sistema operativo, prova a farlo passare attraverso una chiamata di sistema al sistema operativo stesso, scrivendo il tipo e i parametri della chiamata sul proprio stack e effettuando una chiamata trap. Ora, ho capito, ma la domanda è, come fa un programma a sapere che, diciamo, la chiamata "read" su Unix è identificata dalla chiamata "ReadFile" sull'API Win32? Ad esempio, in un programma scritto in C, questa informazione è nota al compilatore? E diciamo che in futuro un nuovo OS introdurrà la chiamata di sistema "foo", che fa esattamente la stessa cosa della "lettura" di Unix ... Beh, come lo saprebbe un programma dell'utente?

    
posta Federico Luzzi 25.02.2017 - 14:29
fonte

4 risposte

6

how does a program know that, let's say, the "read" call on Unix is identified by the "ReadFile" call on the Win32 API? For example, in a program written in C, is this info known by the compiler?

Né il programma né il compilatore lo sanno. Il programmatore sa che su sistemi conformi a POSIX, c'è un file di inclusione chiamato <unistd.h> che ha una funzione da leggere dai descrittori di file con il prototipo ssize_t read(int fd, void *buf, size_t count) e ha un certo comportamento quando viene chiamato. Il compilatore non tratta read() in modo diverso rispetto ad alcune funzioni del tuo programma.

In che modo read() fa il suo business è completamente opaco. Sotto il cofano di Unix, fa tutto ciò che il kernel si aspetta che accada quando si vuole fare una chiamata di sistema. Su Windows, utilizza il meccanismo che Windows rende disponibile per questo. In alcuni ambienti embedded in cui il processo ha accesso diretto al dispositivo, potrebbe eseguire codice che legge direttamente il file.

Questo è ciò che rende il codice portatile: le librerie implementano qualsiasi cosa dettami dallo standard in modo compatibile con l'ambiente locale. Finché le biblioteche e i chiamanti aderiscono agli standard, i programmi funzionano come previsto e tutti sono felici.

    
risposta data 25.02.2017 - 15:39
fonte
4

In genere, le informazioni sulle chiamate di sistema sono rese disponibili per i programmi C da file di intestazione specifici della piattaforma. Cioè, il sistema operativo fornisce una libreria wrapper che contiene le syscalls effettive e offre una comoda interfaccia per i programmatori C. Per comodità, alcune di queste librerie forniscono una funzione syscall() C che gestisce le convenzioni di chiamata syscall (ad esempio inserendo i dati nei registri corretti), ma che richiede comunque al programmatore di conoscere i numeri di syscall e i tipi di argomenti specifici della piattaforma. Su Linux, man 2 intro fornisce ulteriori dettagli.

Ovviamente, l'uso di questa libreria o il richiamo di syscalls direttamente non sono generalmente trasferibili. Per * nix, lo standard POSIX garantisce la compatibilità della sorgente tra vari gusti Unix (vale a dire, la libreria wrapper deve fornire un'interfaccia coerente). Se vuoi che un programma funzioni su diversi sistemi operativi che forniscono interfacce completamente diverse per le sysc, dovrai utilizzare un livello di astrazione. La libreria standard C è uno di questi livelli di astrazione e include funzioni specifiche della piattaforma con un'interfaccia stabile.

Usando il tuo esempio di read() , la funzione C è portatile su sistemi POSIX. La libreria standard C offre invece fread() , che è portabile su tutte le implementazioni C che hanno una libreria standard.

    
risposta data 25.02.2017 - 14:53
fonte
1

Nel kernel di Linux, è possibile accedere alle syscalls impostando il registro eax sul corrispondente valore di syscall e chiamando un interrupt. I valori su altri registri agiscono come argomenti.

Il kernel linux, una volta avviato, associa alcuni degli interrupt a se stesso e quando un programma chiama uno di questi, la CPU salta a una funzione specifica all'interno del kernel. A seconda del valore di eax e degli altri registri, il kernel esegue il syscall corrispondente.

Nel linguaggio C, è possibile accedere alle sysc tramite il codice asm incapsulato come funzioni C.

Ci scusiamo per i miei errori di scrittura.

    
risposta data 26.02.2017 - 18:18
fonte
0

Ci sono molti modi in cui un programma può interfacciarsi con il sistema operativo.

  1. Chiamata alla biblioteca
  2. Funzionalità linguistiche
  3. Shell, Spawn & eseguire chiamate

Una cosa importante da comprendere è che i programmi scritti in linguaggi compilati come C o C ++ sono solo portatili come codice sorgente. Il programmatore sa che certi sistemi operativi forniti da SO sono garantiti per essere disponibili su sistemi complient e il compilatore e il linker forniscono tali informazioni al momento della compilazione utilizzando le librerie di sistema.

Altre lingue che funzionano come sono, vale a dire senza ricostruzione, tendono a fornire un livello di astrazione del sistema operativo o un livello di virtualizzazione che traducono le istruzioni dei programmi su quelle del sistema operativo.

Il nuovo sistema operativo ipotetico dovrebbe fornire le librerie e / o l'OSAL per le lingue supportate.

Uno dei molti problemi di utilizzo di funzioni come sys.call () dove i programmi esegui comandi OS usando shell / spawn / etc., è quello quando tali comandi cambia il software smette di funzionare finché non viene rilasciata una patch o un aggiornamento che rileva il sistema su cui è in esecuzione e invia i comandi corretti.

    
risposta data 26.02.2017 - 19:51
fonte

Leggi altre domande sui tag