Newsgroup: it.comp.os.linux.development
Titolo: chiamate di sistema

Qualcuno mi spiega come funziona quello che c'e tra una chiamata a una 
funzione della glibc e la chiamata a una funzione del kernel? A cosa 
serve mappare le chiamate di sistema in funzioni della glibc? Ho 
realizzato un programma di prova che chiama write, ho compilato con 'gcc 
-static -o prog prova.c' e poi da 'gdb prog' ho dato il comando 
'disassemble write'. Non ho capito bene quello che ho visto: i parametri 
di write vengono presi dallo stack e messi nei registri eax ebx ecc.. e 
poi c'e' solo un int 0x80. Cercando (poco per ora) su google ho visto 
che quell'int 0x80 serve a passare in kernel mode. Ma come fa il kernel 
a sapere cosa deve fare esattamente? Oppure significa semplicemente che 
il codice seguente va eseguito in kernel space?
-- 
Devaraja (Xdevaraja87^gmail^c0mX)
Linux Registerd User #338167
http://counter.li.org

 il codice seguente va eseguito in kernel space?
Mi sembra di ricordare che in eax (o meglio "al", 8 bit) ci vada il
numero che identifica la chiamata di sistema, i parametri vanno
negli altri registri.
-- 
Lorenzo

 
Io vedo un 'mov 0x4,%eax', e' questo che dici? (sembrerebbe cosi')
Quindi write() e' solo una funzione wrapper che fa qualche controllo 
prima di chiamare la funzione di output su stdout del kernel ('mov 
0x4,%eax int 0x80')? Esiste un modo per chiamare (da codice C) 
direttamente una funzione del kernel? Comunque grazie per la risposta.


 direttamente una funzione del kernel? Comunque grazie per la risposta.
Certo, basta fare quello che fa la glibc, inizializzi i registri, fai "int
0x80" e poi tiri fuori estrai il risultato sempre dai registri.
Spiega qual è il tuo scopo, magari arriviamo prima alla risposta
definitiva :)
Ciao,
-- 
 Daniele Orlandi                                                        つづく

Daniele Orlandi ha scritto:

Lo scopo e' imparare come funziona linux ;-)


 Lo scopo e' imparare come funziona linux ;-)
Ottimo. Allora, se non lo hai già, ti consiglio "Understanding the Linux
Kernel" di Daniel P. Bovet e Marco Cesati. E' aggiornato alla 2.4, non vedo
l'ora che esca (se uscirà) la nuova edizione.


 "int 0x80" e poi tiri fuori estrai il risultato sempre dai registri.
Ciao,
 ma questo non e' vero e proprio C ... questo e' assembly! O sbaglio?
 Ciao
 Federico

  ma questo non e' vero e proprio C ... questo e' assembly! O sbaglio?
No, non sbagli, purtroppo non c'è altro modo di manipolare i registri e
tantomeno di mandare un "INT" in C. Io penso all'inline assembly ma,
giustamente, non è C.


 direttamente una funzione del kernel? Comunque grazie per la risposta.
 
man 2 intro
-- 
Lorenzo

 giustamente, non č C.
Puoi usare la macro _syscall.
-- 
Lorenzo

 ha scritto:

syscall(2)
Luca
-- 
Home: 
http://kronoz.cjb.net
La mia opinione puo` essere cambiata, ma non il fatto che ho ragione.

 syscall(2)
Ciao,
 certo, la chiamata a syscall e' puro C ... non c'e' dubbio!
Pero' la syscall non puo' essere scritta in C :-)
 Ciao
 Federico


Certo, la tua CPU esegue direttamente i file sorgenti scritti in C? :-)
Per quel che ne sai anche la printf potrebbe essere scritta in assembly.
Il punto e` che syscall(2) e` una funzione di libreria, e`
un'astrazionem quello che ci sta dietro non deve riguardarti.
Se scrivi direttamente l'asm inline sei vincolato ad una famiglia di CPU
(o peggio ancora ad una singola CPU). Se usi l'astrazione che la
libreria di mette a disposione (vedi syscall) il vincolo cade (di
solito).
Luca
-- 
Home: 
http://kronoz.cjb.net
Collect some stars to shine for you
And start today 'cause there's only a few
A sign of times my friend

 serve mappare le chiamate di sistema in funzioni della glibc? Ho 
Allora:
le glibc non sono altro che dei wrapper per le chiamate di sistema.
Lo schema di funzionamento è questo:
quando chiami una funzione C (tipo mkdir()), la sua definizione è
questa:
inserisce nel registro eax l'identificativo univoco della funzione di
sistema (sys_mkdir) presa dall'array bidimensionale syscall_table (non
ricordo bene se ho azzeccato il nome) ed esegue l'interrupt software 
0x80, che richiama il gestore delle system call. Quest'ultimo, effettua
salvataggi di registri, inserisce i vari parametri negli altri registri,
ed esegue la system call (sys_mkdir()) passando quindi dallo user mode
(chiamata alla glibc) al kernel mode (system call handler), portando 
così a vantaggi di sicurezza perchè viene gestito tutto dal kernel, e
portabilità perchè le interfacce di sistema sono coperte dalla glibc.

 solito).
Non solo, infilare codice asm-inlinea (a meno che non sia stato pensato
apposta per quanto segue) crea grossi problemi al compilatore a fare
alcune ottimizzazioni di base, in quanto assunzioni che si possono fare
sullo strutturato C non possono essere fatte sull'asm.
-- 
non vincono, non vinceranno, non hanno domani
la forza č nel puntello impugnato da oneste fortissime mani

 
Peggio ancora, se non si sa bene su quali registri agisce il
compilatore, si rischia di invalidare alcune informazioni essenziali che
vi erano immagazzinate...
-- 
Matteo Settenvini
FSF Associated Member
Email : 
mat...@member.fsf.org
-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCS d--(-) s+:- a-- C++ UL+++
P?>++ L+++>$ E+>+++ W+++ N++ o?
w--- O- M++ PS++ PE- Y+>++
PGP+++ t+ 5 X- R tv-- b+++ DI+
D++ G++ e h+ r-- y?
------END GEEK CODE BLOCK------

 vi erano immagazzinate...
Per quello pare di ricordare che ci fosse il trucchetto. C'era un metodo
apposta fatto per risolvere questo problema.
Solo che sono totalmente multipiattaforma da qualche annetto e tutta la
roba asm non la uso manco di striscio, con il risultato che me la sono
scordata di brutto (e poi non mi č mai piaciuto lavorare cosě vicino
alla macchina... mannaggia il successo di *nix č basato sul C, e per mia
scelta piů sotto non vado ;) )


 apposta fatto per risolvere questo problema.
C'e` la c.d. "clobber list", che indica al gcc quali registri sono stati
sporcati ed eventualmente se e` stata toccata la memoria (per via del
fatto che il gcc potrebbe tenere in cache in un registro un valore di
memoria che e` stato cambiato dal codice asm).
Sulle ottimizzazioni la cosa e` ancora piu` subdola perche`, sebbene la
porzione di asm inline sia sostanzialmente una blackbox per il gcc, il
compilatore potrebbe decidere di riordinare le istruzioni prima e dopo
il frammento inline... in questo caso viene in aiuto la keyword
volatile, che inibisce il riordino (e come effetto collaterale impedisce
ottimizzazioni locali).
Luca
-- 
Home: 
http://kronoz.cjb.net
"La Via prosegue senza fine."
	Bilbo Baggins - Il Signore degli Anelli - J.R.R. Tolkien

 (chiamata alla glibc) al kernel mode (system call handler),
Il passaggio in kernel mode avviene quando viene generato l'interrupt
(software) 0x80. Inoltre se si usa l'int 0x80 l'ABI prevede che gli
argomenti siano messi nei registri _prima_ della chiamata (quelli in
eccesso vanno eventualmente sullo stack). L'handler dell'int 0x80 si
occupa di sistemare gli argomenti in modo che corrispondano alla
convenzione usata dalle normali funzioni C.
Con kernel e libc recenti, pero`, la cosa non funziona cosi` :-)
La glibc mette gli argomenti nei registri e poi esegue una chiamata di
funzione (call) all'ultima pagina dello spazio di indirizzamento del
processo. Qui` e` mappato un trampolino che esegue la syscall vera e
propria. Se la CPU e` recente verra` usato syscall/sysenter (che sono
piu` veloci dell'int), altrimenti verra` chiamato il solito int 0x80.
Questo trampolino permette alla glibc di eseguire sempre e comunque una
call, sara` poi il kernel stesso ad usare il metodo migliore per
effettuare la syscall.
Luca
-- 
Home: 
http://kronoz.cjb.net
"L'amore consiste nell'essere cretini insieme." -- P. Valery

 eccesso vanno eventualmente sullo stack).
Ehm... quale stack?


 ha scritto:

Giusto, su x86 non si usa (anche se mi rimane il dubbio sul 6 argomento
nei vecchi kernel). Su SH quando ci ho lavorato alcuni argomenti (5-6 se
non sbaglio) venivano messi sullo stack (utente) e copiati poi sullo
stack (kernel) dall'handler, ma ora hanno cambiato anche qui.
Tra parentesi google dice che FreeBSD usa proprio lo stack per passare i
parametri...
Non vedo grossi problemi perche` la page table rimane invariata visto
che l'address space del kernel e` comunque mappato in tutti i processi
usermode. Il vantaggio di usare i registri lo vedo quando si usa un
split 4G/4G, dove l'accesso all'address space del processo e` piu`
macchinoso...
Luca
-- 
Home: 
http://kronoz.cjb.net
Quando un uomo porta dei fiori a sua moglie senza motivo, 
un motivo c'e`.

 stack (kernel) dall'handler, ma ora hanno cambiato anche qui.
Sì, tra l'altro è difficile fare un discorso generico, ogni architettura ha
le sue tecniche, anche la x86 ne ha più d'una, come dici bene tu citando
syscall/sysenter.


 Lo scopo e' imparare come funziona linux ;-)
linuxassembly.org
Ciao
-- 
none

 alta dovrebbe essere da 16 o sbaglio?
al = 8 bit
ah = 8 bit
al + ah = ax = 16 bit
extended ax = 32 bit 
+-------------------------------------------+
|                   E A X                   |
+---------------------+---------------------+
|                     |         AX          |
+---------------------+---------------------+
|          |          |    ah    |    al    |
+----------+----------+----------+----------+
| ........ | ........ | ........ | ........ |
+----------+----------+----------+----------+