PDA

View Full Version : Moduli kernel e ioctl


shodan
06-05-2005, 14:17
Ciao a tutti,

da poco sto cercando di capire come funziona la programmazione in kernel space e sto quindi creando i miei primi moduli (non che siano un granchè, beneinteso :p).

Quello che non riesco a fare è passare in modo corretto le chiamate ioctl della standard library. Per capirci, non riesco a capire come mai il numero "cmd" che arriva al modulo sia incompleto. Vi riporto uno stralcio del codice così che possa spiegarmi meglio...

Funzione userspace:
#define MY_IOCTL '0x0500' //type 5 - number 0
....
a = 10;
file = fopen ("/dev/test", O_RDONLY);
ioctl (file, MY_IOCTL, &a);

Se dentro il modulo kernel stampo il numero "cmd" con una semplice "printk (Ioctl number: %x\n", cmd)" ottengo la seguente stringa: "Ioctl number: 500". Il numero pare corretto, ma secondo me è incompleto, in quanto in base a quello che leggo in asm/ioctl.h il numero ioctl dovrebbe essere più lungo (formato da più bit). Inoltre quest'ipotesi è avvalorata dal fatto che se provo a stampare la dimensione del tipo dai implicato con _IOC_SIZE(cmd), ottengo 0 invece che 4.

Dove sbaglio? :confused:

Ciao grazie! :)

ilsensine
06-05-2005, 14:45
Esiste una codifica accettata per le ioctl; in base a questa convenzione, una ioctl viene definita in funzione:
- di un identificativo arbitrario, unico per il modulo (un char)
- di un indice che enumera la ioctl tra quelle gestite dal modulo (char)
- dalla dimensione dei dati passati (14 bit)
- dalla "direzione" dei dati (input e/o output) (2 bit)
Questi parametri vengono usati per _generare_ il numero effettivo della ioctl (v. asm/ioctl.h)
In particolare:
bit 0..7: numero indice della ioctl per il modulo
bit 8..15: "tipo" (identificativo) della ioctl per il modulo
bit 16..29: dimensione della struttura dati passata
bit 30..31: direzione dei dati
Questo è vero per i386; per altre architetture le codifiche possono benissimo essere differenti.

Imporre ad una ioctl un numero fisso (tipo 0x0500) è deprecato in quanto difficile da mantenere/gestire e ambiguo. Solo le ioctl "legacy" hanno numeri fissi, non codificati. Si preferisce una definizione del tipo:

#define M_IOCTL_NUMERO_0 _IOR ('M', 0, struct my_data_struct)

dove _IOR è una macro che si occupa di codificare una ioctl di lettura (read), di tipo 'M', numero 0, che accetta un puntatore a my_data_struct come parametro.

Vedi ad es. linux/videodev2.h per una definizione di molte ioctl secondo questo formato.

shodan
06-05-2005, 15:03
Ciao a tutti,

da poco sto cercando di capire come funziona la programmazione in kernel space e sto quindi creando i miei primi moduli (non che siano un granchè, beneinteso :p).

Quello che non riesco a fare è passare in modo corretto le chiamate ioctl della standard library. Per capirci, non riesco a capire come mai il numero "cmd" che arriva al modulo sia incompleto. Vi riporto uno stralcio del codice così che possa spiegarmi meglio...

Funzione userspace:
#define MY_IOCTL '0x0500' //type 5 - number 0
....
a = 10;
file = fopen ("/dev/test", O_RDONLY);
ioctl (file, MY_IOCTL, &a);

Se dentro il modulo kernel stampo il numero "cmd" con una semplice "printk (Ioctl number: %x\n", cmd)" ottengo la seguente stringa: "Ioctl number: 500". Il numero pare corretto, ma secondo me è incompleto, in quanto in base a quello che leggo in asm/ioctl.h il numero ioctl dovrebbe essere più lungo (formato da più bit). Inoltre quest'ipotesi è avvalorata dal fatto che se provo a stampare la dimensione del tipo dai implicato con _IOC_SIZE(cmd), ottengo 0 invece che 4.

Dove sbaglio? :confused:

Ciao grazie! :)

Bene, mi rispondo da solo! :p
Il "particolare" che mi era sfuggito è che devo usare le macro dell'header asm/ioctl.h anche nel programma user space... io invece ero convito che era la funzione ioctl a generare il numero corretto a partire dal magic number e dal minor number. Bene... ora i numer generati (sia lato user space che kernel space) sono uguali. Inoltre ho notato che per definire il magic number non devo usare gli apici a meno che non stia usando una singola lettere (non è il caso). Ottimo, altro errore stupido! :D

Grazie lo stesso! :)

shodan
06-05-2005, 15:06
Esiste una codifica accettata per le ioctl; in base a questa convenzione, una ioctl viene definita in funzione:
- di un identificativo arbitrario, unico per il modulo (un char)
- di un indice che enumera la ioctl tra quelle gestite dal modulo (char)
- dalla dimensione dei dati passati (14 bit)
- dalla "direzione" dei dati (input e/o output) (2 bit)
Questi parametri vengono usati per _generare_ il numero effettivo della ioctl (v. asm/ioctl.h)
In particolare:
bit 0..7: numero indice della ioctl per il modulo
bit 8..15: "tipo" (identificativo) della ioctl per il modulo
bit 16..29: dimensione della struttura dati passata
bit 30..31: direzione dei dati
Questo è vero per i386; per altre architetture le codifiche possono benissimo essere differenti.

Imporre ad una ioctl un numero fisso (tipo 0x0500) è deprecato in quanto difficile da mantenere/gestire e ambiguo. Solo le ioctl "legacy" hanno numeri fissi, non codificati. Si preferisce una definizione del tipo:

#define M_IOCTL_NUMERO_0 _IOR ('M', 0, struct my_data_struct)

dove _IOR è una macro che si occupa di codificare una ioctl di lettura (read), di tipo 'M', numero 0, che accetta un puntatore a my_data_struct come parametro.

Vedi ad es. linux/videodev2.h per una definizione di molte ioctl secondo questo formato.


Già, mi sono appena correto! :) Si nota che sono solo agli inizi... ma in fin dei conti un inizio ci deve pur essere! ;)

Grazie ilsensise, sei semple molto gentile!

PS: l'altro giorno mi sono imbattuto quasi per sbaglio in una discussione in cui con fek e cdmauro si discuteva dell'impiegare il C++ all'interno del kernel... posso chiederti che lavoro fai? Perchè mi pareva di capire che scrivi driver di professione (o quasi).
Ciao. :)

ilsensine
06-05-2005, 15:11
Sì tra le altre cose mi è capitato diverse volte di mettere mano al kernel.

shodan
06-05-2005, 15:20
Sì tra le altre cose mi è capitato diverse volte di mettere mano al kernel.

Ciao,

se non sono indiscreto, ti è capitato solo riguardo ai driver o anche relativamente al kernel vero e proprio? Se si qual era lo scopo delle modifiche?

Ciao! :)

ilsensine
06-05-2005, 15:29
Entrambi. Mi occupo spesso di sistemi embedded, quindi mi capita sia di personalizzare il kernel che di scrivere driver appositi.

shodan
06-05-2005, 16:09
Entrambi. Mi occupo spesso di sistemi embedded, quindi mi capita sia di personalizzare il kernel che di scrivere driver appositi.

Per i driver ok, ma per le personalizzazioni al kernel che intendi? :confused:

ilsensine
06-05-2005, 16:35
Cose del tipo API di gestione dma, gpio, e tutta una serie di modifiche necessarie se hai una scheda progettata ad hoc per fare cose particolari.

shodan
06-05-2005, 16:43
Cose del tipo API di gestione dma, gpio, e tutta una serie di modifiche necessarie se hai una scheda progettata ad hoc per fare cose particolari.

Capito, quindi tutte cose legate all'hardware. :)
Ciao. :)