|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Messaggi: n/a
|
Domanda su sistemi operativi linux e programmazione.....mi aiutate a capire!?
ciao a tutti
mi domandavo una cosa riguardante la programmazione e i sistemi operativi. un sistema operativo ha numerose funzioni, chiamate di sistema, che un programma può lanciare. il problema è questo. come può farlo? il s.o. è compilato quindi è codice macchina puro. come può un programma c++ interfacciarsi alle chiamate di sistema? cioè io chiamo una fork per esempio in un programma c++. esso viene compilato in codice macchina. ora come si interfaccia la mia fork col codice macchian del s.o.?? cosa sono ste chiamate di sistema? esiste nel s.o. anche una versione non compilata richiamabile da un programma c++? sighhh confusooo |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Jan 2008
Messaggi: 8406
|
Capisco, ti riferisci alle cosidette syscall.
Innanzitutto vorrei chiarire il fatto che pure una chiamata ad una funzione presente in una libreria esterna, è una chiamata ad un qualcosa di compilato e il codice sorgente non c'è anche in questo caso. Detto questo, il fork che tu chiami è una chiamata alla libc, cioè una libreria "basilare" che tutti gli os hanno ( tranne qualche os particolare ). E' il passo successivo, cioè come fa la libc a chiamare il sistema operativo che è "strano". Ci sono vari metodi per eseguire questo genere di chiamate. Il più noto è l'uso di interrupt. In pratica, il sistema operativo riserva per sè stesso un vettore di interrupt ( cioè uno degli interrupt disponibili sull'architettura hardware ). Esempio banale sotto linux: Codice:
mov edx,len mov ecx,msg mov ebx,1 mov eax,4 int 0x80 Nei vari registri vengono stoccati i parametri da passare alla syscall. Quali registri usare e come usarli dipende dalle convenzioni stabilite da chi ha creato il sistema operativo. Ovviamente la cpu sa dove trovare la tabella degli interrupt e nella 128-esima casella di tale tabella c'è memorizzato l'indirizzo a cui trasferire il controllo nel caso venga chiamato l'int 0x80 ( 0x80 = 128 in decimale ). Se invece vai a guardare lo stesso codice, ma per architetture x86_64, troverai una cosa del genere: Codice:
mov rax, 1 mov rdi, 1 mov rsi, msg mov rdx, len syscall Il punto è che il metodo qui è diverso, perchè si usano alcuni registri della cpu ( i model specific registers ) per conservare l'indirizzo a cui tasferire il controllo qualora venga fatta una syscall. Ovviamente all'indirizzo in questione c'è una routine del sistema operativo che controlla il contenuto di eax/rax e quindi chiama le opportune subroutine per eseguire la syscall richiesta. Ovviamente ho dato una spiegazione di massima, trascurando completamente il fatto che si passa da ring 3 a ring 0 e altre operazioni che vengono svolte durante l'invocazione delle syscall. Esistono alcuni altri metodi per svolgere quest'operazione, ma sono decisamente poco usati o caduti in disuso. I principali metodi sono i due che ho citato sopra. Ultima modifica di pabloski : 19-09-2012 alle 15:49. |
![]() |
![]() |
![]() |
#3 |
Messaggi: n/a
|
c
grazie mille!
quindi in pratica uno deve sapere come è la funzione pre compilazione passargli i giusti parametri in base a questo e anche se non è codice sorgente ci pensa il compilatore a far funzionare il tutto. ciao! |
![]() |
![]() |
#4 | |
Senior Member
Iscritto dal: Jan 2008
Messaggi: 8406
|
Quote:
I due meccanismi sono profondamente diversi. Il concetto di base è sempre quello di far un salto ad una locazione di memoria dove si sa che c'è l'entry point di una certa funzione. Ma nel caso di librerie a collegamento dinamico, la cosa avviene in maniera molto diversa rispetto ad una syscall. Gli esempi che ho riportato riguardano le chiamate a sistema operativo, cioè le syscall. In quel caso il compilatore ( assemblatore visto che gli esempi sono in assembly ) non fa assolutamente nulla per capire dove andare a pescare le funzioni da chiamare. |
|
![]() |
![]() |
![]() |
#5 |
Messaggi: n/a
|
c
entrambe a questo punto
![]() quindi nel caso di una chiamata a libreria è l'assemblatore che sa dove è la cella di memoria del codice macchina corrispondente all'entry point della funzione. nel secondo caso syscal si fanno uso degli interrupt. spero di aver capito a sto punto.....se no rinuncio ![]() in entrambi i casi però mi confermi che bisogna conoscere come è fatta la funzione sia syscall che dll per sapere quali parametri passare e come è fatta (cioè bisogna capire come è il codice sorgente) accetto pure spiegazioni in pvt se non vogliamo prolungare sta domanda che per molti immagino sia banale |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: Jan 2008
Messaggi: 8406
|
A grandi linee il concetto è quello. L'unica differenza è che nel caso delle librerie, il metodo per trovare gli entry point delle funzioni sfrutta informazioni memorizzate sul file eseguibile stesso.
Nel caso delle syscall, c'è un indirizzo memorizzato o nella tabella degli interrupt o in registri chiamati MSR. Riguardo i parametri, la funzione chiamata e il chiamante devono mettersi d'accordo sulle convenzioni da usare. Questa cosa è parte di quella che si chiama ABI. Per esempio in una classica chiamata a funzione C, si mettono nello stack i parametri da passare. La funzione va nello stack, li preleva e li usa. Nell'architettura x86_64 invece si fa maggior uso dei registri ( perchè c'è ne sono fisicamente di più ) e lo stack si usa solo in determinati casi. Ma si tratta in entrambi i casi di convenzioni prestabilite, non c'è niente di obbligatorio e in teoria si può fare come si vuole ( ovviamente non rispettare le convenzioni standard porta a creare software incompatibile col resto del mondo ). Comunque meglio continuare qui, magari qualcun'altro aggiungerà qualcosa o espliciterà meglio taluni concetti. Dopotutto non si tratta affatto di cose banali, soprattutto la parte che riguarda le syscall. Ultima modifica di pabloski : 19-09-2012 alle 19:28. |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 14:38.