2012-08-16 4 views
11

Nota: Sto elencando questo problema come è oggi, sono non contrario a cambiare l'implementazione (spostando la creazione della classe in un'area comune per esempio) se rende le cose più facili ... Non sono sicuro di come farlo. : End NoteIn Linux, come usi device_create all'interno di una classe esistente?

Ho due moduli del kernel linux e sto cercando di aggiornare le voci/sys per loro. Cercando in giro su google e da altre fonti, ho visto un sacco di codice lungo le linee di:

static dev_t MyDev; 
static struct class *c1; 

static int __init start_func(void) 
{ 
    ... 
    MyDev = MKDEV(nMajor, MINOR_VERSION); 
    register_chrdev_region(MyDev, 1, MODULE_NAME); 
    c1 = class_create(THIS_MODULE, "chardrv"); 
    device_create(c1, NULL, MyDev, NULL, MODULE_NAME); 
    .... 

E ho verificato per il mio primo modulo di questo codice funziona, e che crea correttamente un:

/sys/class/chardrv/<MODULE_NAME> 

ingresso. Quello che mi piacerebbe sapere è come si crea un dispositivo in una classe esistente. In altre parole, uno dei miei moduli ha creato questa nuova classe Chardrv, ora voglio che anche il mio altro modulo possa registrare i suoi dispositivi nella stessa classe.

non posso chiamare class_create() di nuovo (nel secondo modulo), perché quella classe "chardrv" esiste già ...

Così posso eseguire un controllo per vedere se/sys/class/chardrv esiste, e questo può aiutarmi a decidere se devo chiamare class_create() o no, non è un problema. Consente di mettere un po 'pseudo codice qui per chiarire:

if (path "/sys/class/chardrv" does not exist) 
    new_class = class_create("chardrv") 
else 
    new_class = some how get class "chardrv" handle, or properties, or whatever 
device_create(new_class, ...) 

Così come da questo esempio, se la mia classe esiste già, e voglio solo aggiungere il mio nuovo dispositivo in esso da un secondo modulo Presumo che ho bisogno per creare una struttura di classe e in qualche modo popolarla con gli attributi di "classe chardrv", quindi chiamare device_create come prima, ma non sono sicuro di come farlo.

risposta

-1

Il kernel Linux non consente di farlo. Questo è l'ERRORE che otterrai.

**[ 865.687824] kobject_add_internal failed for net with -EEXIST, don't try to register things with the same name in the same directory. 
[ 865.687835] Pid: 6382, comm: insmod Tainted: P  W O 3.2.16.1JeshuLinux #1 
[ 865.687840] Call Trace: 
[ 865.687849] [<c1584382>] ? printk+0x2d/0x2f 
[ 865.687859] [<c12a5438>] kobject_add_internal+0x138/0x1d0 
[ 865.687869] [<c12a5a11>] kset_register+0x21/0x50 
[ 865.687879] [<c137b63d>] __class_register+0xcd/0x1b0 
[ 865.687888] [<f8d0a0aa>] hello_init+0x4a/0x80 [sysfs_Dev] 
[ 865.687897] [<c1003035>] do_one_initcall+0x35/0x170  
[ 865.687909] [<f8d0a060>] ? enable_show+0x40/0x40 [sysfs_Dev]  
[ 865.687919] [<c10928d0>] sys_init_module+0x2c0/0x1b50  
[ 865.687941] [<c159485f>] sysenter_do_call+0x12/0x28  
[ 865.687947] Registering Class Failed** 

If you want to understand sysfs read: [mochel.pdf](www.kernel.org/pub/linux/kernel/people/mochel/doc/papers/ols-2005/mochel.pdf) 
+1

Non sono sicuro che tu sia chiaro quando sto cercando di farlo qui ... almeno quell'errore non ha senso per la mia domanda. Voglio creare una classe "chardrv" per esempio, quindi avere un modulo del kernel registrare un dispositivo in esso. Dì "dispositivo1". Quindi un secondo modulo del kernel registrerà un secondo dispositivo nella stessa classe "dispositivo2". Quindi ora l'esecuzione di un comando di lista su/sys/class/chardrv mostrerà entrambi i dispositivi. Stai dicendo che non c'è modo di farlo in Linux? Non mi sembra giusto ... – Mike

3

di seguire il vostro codice di esempio, si potrebbe semplicemente chiamare device_create() di nuovo, passando per la stessa classe, ad esempio:

MyDev = MKDEV(nMajor, MINOR_VERSION); 
register_chrdev_region(MyDev, 1, MODULE_NAME); 
c1 = class_create(THIS_MODULE, "chardrv"); 
device_create(c1, NULL, MyDev, NULL, MODULE_NAME); 
... 
device_create(c1, NULL, MyDev2, NULL, "mydev2"); 

Non si dovrebbe sicuramente bisogno di controllare il percorso al fine di determinare se la classe è stato creato. Lo stai creando nel tuo codice, quindi prova semplicemente per c1 == NULL o usa una bandiera se devi.

+0

Per questo semplice caso d'uso, sì, funzionerà. Che dire quando ho un secondo dispositivo del kernel? Quando ho rifinito la mia domanda ho detto che un modulo _second_ del kernel vorrà anche creare un dispositivo nello stesso/sys/class/chardrv directroy. Ovviamente non c'è bisogno di chiamare 'class_create()' in entrambi i posti. Ma se non chiamo questo metodo, come posso accedere alla mia classe chardrv necessaria per il parametro 1 di 'device_create()'. Ancora una volta: ** Modulo 1 ** chiama 'class_create()/device_create()'. ** Il Modulo 2 ** vuole solo chiamare 'device_create()', ma richiede il riferimento alla classe. – Mike

+0

Quindi è necessario aggiungere un'API per recuperare la classe. L'opzione più semplice è quella di inserirla nel kernel corretto (non un modulo) e fare in modo che i moduli vi chiamino. – mpe

+0

E sto bene, l'implementazione è flessibile. Tuttavia non sono ancora sicuro di come. Quando chiamo 'class_create()' parameter1 è 'THIS_MODULE'. Spostando la creazione della classe nel kernel corretto, presumo che 'THIS_MODULE' non funzioni più. La def della funzione class_create dice P1 è: "_owner: puntatore al modulo che possiede questa struct class_". Ciò implica che il proprietario deve essere un modulo. – Mike

6

Per utilizzare la funzione device_create con la stessa classe, basta passarla a un puntatore della stessa classe.

Poiché si desidera chiamare device_create in un modulo diverso da quello in cui si crea la classe, è necessario esportare il simbolo per il puntatore alla classe. È possibile utilizzare la macro per farlo.


Ad esempio:

module1.c:

extern struct class *c1; /* declare as extern */ 
EXPORT_SYMBOL(c1);   /* use EXPORT_SYMBOL to export c1 */ 

static dev_t mod1_dev; 
static int __init start_func(void) 
{ 
     ... 
     /* define class here */ 
     c1 = class_create(THIS_MODULE, "chardrv"); 

     /* create first device */ 
     device_create(c1, NULL, mod1_dev, NULL, "mod1_dev"); 
     .... 
} 

Module2.c

extern struct class *c1; /* declare as extern */ 

static dev_t mod2_dev; 
static int __init start_func(void) 
{ 
     ... 
     /* c1 is defined in module 1 */ 

     /* create second device */ 
     device_create(c1, NULL, mod2_dev, NULL, "mod2_dev"); 
     .... 
} 

Nota: è necessario inserire module1 prima Module2 dal momento che il puntatore classe è definita ed esportati in module1.

Questo dovrebbe creare le directory che ti aspetti:

  • /sys/class/chardrv/mod1_dev
  • /sys/class/chardrv/mod2_dev

A proposito, se hai trovato un errore Invalid parameters quando si tenta di caricare il secondo modulo, potrebbe essere necessario add a KBUILD_EXTRA_SYMBOLS line to your Makefile.

0

Basta creare la classe nella funzione di inizializzazione del modulo del primo modulo, esportare il simbolo della classe globale con EXPORT_SYMBOL e utilizzarlo dall'altro modulo.

Poiché il proprietario della classe è il primo modulo, ogni volta che si aggiunge un dispositivo a quella classe, il contatore di riferimento del primo modulo verrà aumentato: non è possibile scaricarlo mentre qualcuno lo sta utilizzando.

Problemi correlati