|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Member
Iscritto dal: Oct 2007
Città: Terlago --> Trento
Messaggi: 88
|
[Kernel] kthread e accesso ai device
Allora, ho un problema con la programmazione del kernel.
Mi è stato chiesto di realizzare un modulo che: creo due device (char) e creo dei kthread (che attendono ciclicamente degli input su uno dei device). Codice:
static int output_thread(void *arg) { while (!kthread_should_stop()) { wait_for_completion(&available_data); printk("1"); //è solo per test return 0; } Noi a lezione abbiamo fatto solo cat da spazio utente per estrarre i dati del device, ma come si può fare da kthread. Oppure, avete un approccio diverso a questo esercizio per risolvere il problema? Grazie |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Il kernel thread viene eseguito in un contesto di processo diverso dal processo utente che effettua la scrittura, quindi non ha modo di accedere direttamente ai dati. Devi usare quindi un buffer intermedio che riempi direttamente nella read e leggi nel kernel thread (protetto da un mutex o uno spinlock ovviamente).
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
![]() |
![]() |
![]() |
#3 |
Member
Iscritto dal: Oct 2007
Città: Terlago --> Trento
Messaggi: 88
|
ah, ho capito.. non lo sapevo, vabbè peccato sarebbe stato molto più comodo accedere direttamente con il kernel.
dovrò fare così perfetto grazie mille per l'info ci sentiamo più avanti (non credere che i problemi siano già finiti ![]() Bye. e grazie ancora |
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Jul 2002
Città: Milano
Messaggi: 19148
|
non puoi accedere a memoria in user space da kernel
le funzioni copy_to_user e copy_from_user sono fatte apposta ![]() quando il processo in user space fa una write sul dispositivo a caratteri viene chiamata la funzione che tu hai specificato nella struttura fops per rispondere ad una scrittura lì metti la copy_from_user per prendere i dati che l'utente ha scritto |
![]() |
![]() |
![]() |
#5 | |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
Puoi spiegare esattamente cosa devi fare? Forse la soluzione è banale, a che ti serve un kernel thread?
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
![]() |
![]() |
![]() |
#6 |
Member
Iscritto dal: Oct 2007
Città: Terlago --> Trento
Messaggi: 88
|
Si si, intendevo kernel thread, ho dimenticato una parola.
![]() praticamente i kthread devono ciclicamente attendere -sul device chiamato controllo- delle richieste (che verranno fatte da spazio utente sullo stesso device). le richieste contengono una parola, un tempo e una priorità, il kthread deve solo prendere la parola e stamparla con una printk una volta al secondo per un tempo t. Se non ci sono kthread disponibili (perchè tutti stanno stampando)metto le richieste in una coda in attesa che un kthread finisca di servire una richiesta e prenda quella in coda. Però è un progetto per scuola quindi devo proprio svilupparlo così, con i kthread. non è che ho altre scelte. Tu come mi consiglieresti di procedere? Faccio un buffer intermedio e i kthread prendono le richieste da lì? Perchè il mio dubbio è la .read della struttura fops non ho modo di chiamarla io diciamo manualmente con una cat per poi passare i dati al kthread. ma qunado faccio la .write questa mi sblocca un kthread (in attesa su una completion) e quindi non so come prendere i dati della .write Consigli? grazie. Spero di essermi spiegato decentemente altrimenti ti posso postare i pezzi di codice. |
![]() |
![]() |
![]() |
#7 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Abbastanza semplice sembra; non devi però usare il completion, ma una waitqueue.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
![]() |
![]() |
![]() |
#8 | |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
![]() |
![]() |
![]() |
#9 |
Member
Iscritto dal: Oct 2007
Città: Terlago --> Trento
Messaggi: 88
|
ok capito.....allora procedo con le waitqueue.
Grazie mille per i consigli. |
![]() |
![]() |
![]() |
#10 |
Member
Iscritto dal: Oct 2007
Città: Terlago --> Trento
Messaggi: 88
|
Ciao, avrei un'altra domandina riguardo il programma descritto sopra.ù
Allora, io ho fatto il mio kthread che prende i dati da un buffer riempito dalla write, adesso però dovrei implementare anche una specie di log per il kthread, cioè ad esempio quando il kthread parte e si ferma sulla waitqueue io dovrei loggare l'evento "il thread è in attesa di richieste e blablabla" scrivendo su un altro device creato appositamente (che poi potrà venire letto con una cat /dev/logging). Posso scrivere dal kthread direttamente sul device? se si come potrei fare e i dati scritti posso visualizzarli tranquillamente con una cat? Grazie e ciao. |
![]() |
![]() |
![]() |
#11 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Non ha senso questa affermazione. Il tuo driver _è_ il device. Potresti (duale della precedente) riempire un buffer dal thread e passarlo in userspace dalla read.
Però non reinventarti la ruota, esistono tanti metodi per il logging. Uno già lo conosci (printk), ma ci sono anche debugfs/netlink/sysfs/connector ecc. Nel tuo caso vedo bene il connector, non un device node.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
![]() |
![]() |
![]() |
#12 | ||
Member
Iscritto dal: Oct 2007
Città: Terlago --> Trento
Messaggi: 88
|
EDIT: Scusate sono veramente fuso!! ho già risolto il problema.
Quote:
Non so perché ma c'era questo comando!! probabilmente per debug. vabbè........ Di nuovo ciao a tutti. Intanto grazie per i vostri consigli, abbiamo quasi finito il progetto. Quote:
Ora, ho un ultimo problemino. Non sono proprio pratico dei device e non capisco perché nel progetto quando vado a fare una lettura sul device "log" tutto ok però quando faccio una scrittura sul device "controllo" mi viene anche fatta una lettura su quello di "log", il che è abbastanza seccante perché l'utente dovrebbe decidere lui quando fare una lettura del log e non che mi venga stampata ogni volta che faccio una scrittura (tra l'altro su un altro device!!) Sono abbastanza sicuro che il problema sta in conflitti che forse creo durante le open dei device. Cmq vi posto il codice perché proprio non riesco a venirne a capo. Grazie infinite. Ciao. Codice:
#include <linux/poll.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/miscdevice.h> #include <linux/list.h> #include <linux/string.h> #include <linux/delay.h> #include "ex_thread.h" #include "ex_dev.h" int nthread = 1; int coda = 1; int num = 0; static struct miscdevice log_out_device; static struct miscdevice controllo_out_device; static int my_len; char logging[2048] = ""; struct node blist; struct node* iter; int list_full() { return (num == coda); } int list_vuota() { return (num == 0); } int list_insert(struct node *n) { while(list_full()) { mutex_unlock(&buff_m); strcat(logging, "La coda e' piena! richiesta in attesa.\n"); wait_for_completion(&coda_piena); mutex_lock(&buff_m); } if(list_vuota()) { num++; list_add(&n->list, &(blist.list)); strcat(logging, "Una richiesta e' stata inserita in coda\n"); return 1; } struct node *tmp = NULL; num++; struct list_head* l; list_for_each(l, &blist.list){ tmp = list_entry(l, struct node, list); if(tmp->p < n->p) { list_add_tail(&n->list, &tmp->list); strcat(logging, "Una richiesta e' stata inserita in coda\n"); return 1; } } list_add(&n->list, &tmp->list); strcat(logging, "Una richiesta e' stata inserita in coda\n"); return 1; } static int log_open(struct inode *inode, struct file *file) { int *cont; cont = kmalloc(sizeof(int), GFP_USER); if (cont == NULL) { return -1; } *cont = 0; file->private_data = cont; return 0; } static int controllo_close(struct inode *inode, struct file *file) { return 0; } static int log_close(struct inode *inode, struct file *file) { return 0; } ssize_t log_read(struct file *file, char __user *p, size_t len, loff_t *ppos) { int err, res; int *cont; cont = file->private_data; if (*cont == 1) { return 0; } err = copy_to_user(p, logging, 2048); if (err) return -EFAULT; *cont = 1; return 2048; } ssize_t controllo_write(struct file *file, const char __user * buf, size_t count, loff_t *ppos) { int err; printk("%s",logging); mutex_lock(&buff_m); if (my_pointer) { mutex_unlock(&buff_m); return -1; } my_pointer = kmalloc(count, GFP_USER); if (my_pointer == NULL) { mutex_unlock(&buff_m); return -1; } my_len = count; err = copy_from_user(my_pointer, buf, count); if (err) { mutex_unlock(&buff_m); return -EFAULT; } char msg[25]; int t, p; sscanf(my_pointer, "%s %d %d", msg, &t, &p); struct node* tmp; tmp = (struct node*)kmalloc(sizeof(struct node), GFP_USER); if(!tmp) { return(-1); } strcpy(tmp->msg, msg); tmp->t = t; tmp->p = p; list_insert(tmp); my_pointer = NULL; wake_up_interruptible(&my_waitqueue); mutex_unlock(&buff_m); return count; } int device_create(void) { misc_register(&controllo_out_device); return misc_register(&log_out_device); } void device_destroy(void) { misc_register(&log_out_device); } static struct file_operations log_fops = { .owner = THIS_MODULE, .read = log_read, .open = log_open, .release = log_close, }; static struct miscdevice log_out_device = { MISC_DYNAMIC_MINOR, "log", &log_fops }; static struct file_operations controllo_fops = { .owner = THIS_MODULE, // .open = controllo_open, .release = controllo_close, .write = controllo_write, }; static struct miscdevice controllo_out_device = { MISC_DYNAMIC_MINOR, "controllo", &controllo_fops }; module_param(nthread, int, 0000); MODULE_PARM_DESC(nthread, "numero dei thread"); module_param(coda, int, 0000); MODULE_PARM_DESC(coda, "grandezza della coda"); Ultima modifica di Dawidh : 03-12-2007 alle 08:26. |
||
![]() |
![]() |
![]() |
#13 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Ora sono un pò occupato, appena posso do una occhiata. Se intanto puoi allegare i sorgenti completi, lì sembra che manchi qualcosa...
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
![]() |
![]() |
![]() |
#14 |
Member
Iscritto dal: Oct 2007
Città: Terlago --> Trento
Messaggi: 88
|
No no, tranquillo... non serve più, ho messo anche l'edit in rosso perché non mi ero proprio accorto che avevo messo una printk di troppo che stampava il buffer contenente il log.
![]() grazie per l'interessamento cmq, adesso il programmino funziona benone. Ciao. |
![]() |
![]() |
![]() |
#15 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Ok, credevo ci tenevate a farlo "bene"
![]() (almeno, correggete il macroscopico bug nella log_read prima che il prof vi uccide ![]()
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 Ultima modifica di ilsensine : 03-12-2007 alle 12:13. |
![]() |
![]() |
![]() |
#16 |
Member
Iscritto dal: Oct 2007
Città: Terlago --> Trento
Messaggi: 88
|
bug, c'è un bug nella read? eppure è proprio come quella che ha fatto il prof negli esempi mi sembra strano.l'abbiamo solo adattata alle nostre esigenze ma è come l'ha fatta lui, cosa c'è che non va?non riesco proprio a vederlo
cmq l'esercizio di per se era un esercizio di sincronizzazione, gestire bene mutex, wait e quelle cose lì......linked list con priorità, bloccaggio client se la list è piena... etc... (ci ha addirittura detto che è lo stesso se togliendo il modulo crasha tutto... quindi immagina ![]() oggi abbaimo messo tutto un pò a posto, anche i memleak.... quello che ho postato era ancora solo un abbozzo non il definitivo.... Ultima modifica di Dawidh : 03-12-2007 alle 19:40. |
![]() |
![]() |
![]() |
#17 | |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
int fd = open("/dev/log", O_RDONLY); read(fd, buf, sizeof(buf)); // kabum application buffer overflow
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 09:37.