Newsgroup: it.comp.os.linux.development
Titolo: Aiuto con un kernel module di prova...

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Questo è il codice:
#include <linux/module.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <asm/uaccess.h>
#define MY_MAJOR 123
#define TEXT_SIZE 64
#define TYPE(dev) (MINOR(dev) >> 4) /* high nibble */
#define NUM(dev) (MINOR(dev) & 0xf) /* low nibble */
MODULE_LICENSE("GPL");
char *text;
int my_open(struct inode *inode, struct file *filp){
	int num, type;
	num = NUM(inode->i_rdev);
	type = TYPE(inode->i_rdev);
	printk(KERN_ALERT "Aperto: num = %d, type = %d\n", num, type);
	return 0;
}
int my_release(struct inode *inode, struct file *filp){
	printk(KERN_ALERT "Rilascio\n");
	return 0;
}
ssize_t my_read(struct file *filp, char *buf, size_t count, loff_t *f_pos){
	if (count >= TEXT_SIZE){
		count = TEXT_SIZE - 1;
	}
	if(copy_to_user(buf, text, count)){
		printk(KERN_ALERT "Errore nella lettura\n");
	}
	printk(KERN_ALERT "Letto\n");
	*f_pos += count;
	return count;
}
ssize_t my_write(struct file *filp, const char *buf, size_t count,
loff_t *f_pos){
	if(count >= TEXT_SIZE){
		count = TEXT_SIZE - 1;
	}
	if(copy_from_user(text, buf, count)){
		printk(KERN_ALERT "Errore nella scrittura\n");
	}
	printk(KERN_ALERT "Scritto\n");
	*f_pos += count;
	return count;
}
struct file_operations my_fops = {
    open:       my_open,
    release:    my_release,
    read:       my_read,
    write:      my_write,
};
int init_module(void) {
	printk(KERN_ALERT "Modulo Pronto\n");
	int result;
	result = register_chrdev(MY_MAJOR, "mydev", &my_fops);
	if (result){
		printk(KERN_ALERT "Errore nella registrazione del device\n");
		return -ENODEV;
	}
	text = kmalloc(TEXT_SIZE, GFP_KERNEL);
	if (text == NULL){
	  printk(KERN_ALERT "Memoria insufficiente");
	  return -ENOMEM;
	}
	text="Ciao!";
	return 0;
}
void cleanup_module(void) {
	printk(KERN_ALERT "Goodbye cruel world\n");
	kfree(text);
	unregister_chrdev(MY_MAJOR, "mydev");
}
- ------------------------------
quando carico il modulo va tutto bene, non ho ancora provato a svolgere
operazioni di scrittura o lettura perchè tanto il problema si presenta
prima: se tento di rimuovere il modulo si blocca dopo aver stampato
"Goodbye Cruel World", quindi su kfree o su unregister_chrdev.
Dov'è l'errore? Ammetto di non essere ferratissimo con il C, ma io ho
creato il mio bel puntatore a char globale, gli ho assegnato un
indirizzo allocato con kmalloc (assicurandomi che ci sia mem a
sufficienza), ho assegnato al buffer il valore "Ciao!\0\0\0\0\..." e poi
ho richiamato kfree sul buffer... Mi sono perso qualcosa?
- --
Sostituisci 'r' alla x nel mio indirizzo per rispondermi.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - 
http://enigmail.mozdev.org
iD8DBQFAtMju4lhWScnOpZYRAlSWAJ0cQ8atyF08ySKfwHOiwLJa5GbxrACfdbpk
CclE9Pm2WGdr3hB0wFv+mPU=
=BC4Y
-----END PGP SIGNATURE-----

 }
tu qui vuoi leggere i dati dell'utente, e allora mi sa che ti serve
copy_from_user, non copy_to_users.
e poi nella my_write dovresti avere il problema duale.

 }
Mah, io punterei il dito sulla penultima riga:
text="Ciao!";
se text e' allocata dinamicamente, poi gli assegni un puntatore ad una
costante, ed il kfree() dopo riceve un puntatore diverso da quello
generato dalla kmalloc. Io la cambierei in:
strcpy(text,"Ciao!");
sempre che strcpy sia kernel-compatibile :-P
-- 
Mario "Reliant" Pascucci
Linux user #327002 - 
http://counter.li.org/
http://ilpettegolo.altervista.org/

 ha scritto:

No, e` corretto. file_operations->read viene chiamata quando l'utente
effettua una read sul char dev in questione. L'utente si aspetta quindi
di *ricevere* dei dati. Idem per la write.
Luca
-- 
Home: 
http://kronoz.cjb.net
Una donna sposa un uomo sperando che cambi, e lui non cambiera`. Un
uomo sposa una donna sperando che non cambi, e lei cambiera`.

        text="Ciao!";
hai un memory leak (ed a livello di kernel quella memoria e` *veramente*
persa) ed inoltre la chiamata a kfree in cleanup ha un comportamento non
definito. Quello che ti serve e`:
 
        strlcpy(text, "Ciao!", TEXT_SIZE);
Il problema che hai, comunque, ha poco a che fare con la programmazioni
di moduli del kernel, e` proprio una lacuna sulla basi del C. Stai molto
molto attento a giocare con i moduli, una stupidata come quella puo`
costarti il filesystem.
Luca
-- 
Home: 
http://kronoz.cjb.net
Al termine di un pranzo di nozze mi hanno dato un
amaro alle erbe cosi' schifoso che perfino sull'etichetta
c'era un frate che vomitava.

 }
Mi e` sfuggita un'altra cosa: non utilizzi f_pos ne` per la scrittura
ne` per la lettura. Non e` necessariamente sbagliato, ma tieni conto che
la lettura o la scrittura non avranno mai fine. In pratica se fai una
cosa del genere:
int fd = open("/dev/mydev", O_RDONLY);
while(read(fd, buff, count) {
        something();
}
il ciclo sara` infinito. Se vuoi un comportamento piu` "normale" devi
utilizzare f_pos per leggere/scrivere partendo da una certa posizione
all'interno del tuo buffer (ovviamente aggiungendo dei controlli in modo
da non sforare mai) e restituire 0 nel caso la lettura/scrittura inizi
dopo TEXT_SIZE:
        if (*f_pos >= TEXT_SIZE)
                return 0;
        if (count > TEXT_SIZE - *f_pos)
                count = TEXT_SIZE - *f_pos;
        if(copy_to_user(buf, text, count))
                /* Se fallisci la copia non mentire incrementando f_pos */
                return -EFAULT;
 
        *f_pos += count;
        return count
Luca
-- 
Home: 
http://kronoz.cjb.net
Non capisco tutta questa eccitazione per il Multitasking: 
io sono anni che leggo in bagno.

 Luca
sicuramente ci sarà qualche errore ma ci penserò in seguito, per il
momento il problema è nell'allocazione di text e nella sua "liberazione"
- --
Sostituisci 'r' alla x nel mio indirizzo per rispondermi.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - 
http://enigmail.mozdev.org
iD8DBQFAtQPc4lhWScnOpZYRAuN6AJ0XuE8/rd6k5SoCdx+c2SchEaYZewCcCgXy
qltd1oOOYnykV9kSbM29HJs=
=N77r
-----END PGP SIGNATURE-----

 sempre che strcpy sia kernel-compatibile :-P
Devo ancora provarlo (vedi il mio post precedente, ogni volta mi tocca
riavviare due volte al posto che una) ma credo che il problema sia
proprio lì. In effetti assegno a text un (const char *) che viene
liberato quando esco dalla funzione. Quando chiamo kfree text è un
dangling pointer no?
Non sono abituato a lavorare ad un livello così basso, grazie :-)
- --
Sostituisci 'r' alla x nel mio indirizzo per rispondermi.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - 
http://enigmail.mozdev.org
iD8DBQFAtQ3P4lhWScnOpZYRAsa8AJ9OS4vt+YTQ+AOw3Mx5Cb/fBLNCkgCdGP7q
FBwSIKkFgo1UhwiCtV0e37U=
=WfPn
-----END PGP SIGNATURE-----

 Quando chiamo kfree text è un dangling pointer no?
E` questo :) Oltre al leak ed al fatto che la stringa puntata e` RO (e
tu cerchi di scriverci).
Luca
-- 
Home: 
http://kronoz.cjb.net
Dicono che  il cane sia  il miglior  amico dell'uomo. Secondo me  non e`
vero. Quanti dei vostri amici avete fatto castrare, recentemente?


questo č voluto: l'area di memoria deve essere riferita al modulo e non
ai singoli device (tanto questo modulo č comunque inutile '^^), quanto
al locking, una cosa per volta :-)

eeh lo so... purtroppo ho solo un infarinatura di c++ e negli ultimi
tempi ho utilizzato molto python, mi ero dimenticato di quanto fossero
pericolosi sti leak... e anche con il c++ ero abituato a lavorare ad un
livello piů altino. Non mi ricordavo piů la storia del const * char
quando si assegnano stringhe a puntatori di char...
Dici che č cosě pericoloso? Alla fine sono 64 bytes, un dato importante
in attesa di essere memorizzato sul disco deve proprio trovarsi li? ^_^
Grazie comunque. Se magari sai rispondere al mio post precedente
potresti rendere il mio ambiente di sviluppo meno ostile...
- --
Sostituisci 'r' alla x nel mio indirizzo per rispondermi.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - 
http://enigmail.mozdev.org
iD8DBQFAtRDz4lhWScnOpZYRAkEwAJ9glDPpVsTVXjjQ1nZFrvQQgHoxtACfeWNZ
lDrCEvTSz3WihsIzWsFF9YU=
=TMoz
-----END PGP SIGNATURE-----

 in attesa di essere memorizzato sul disco deve proprio trovarsi li? ^_^
In questo caso l'errore e` (quasi) innocuo, oltre ad una perdita di
memoria non ci sono altri effetti collaterali. Ma usare i puntatori alla
leggera puo` portare alla corruzioni di dati all'interno del kernel...
se quei dati fanno parte del VFS... boom!
Luca
-- 
Home: 
http://kronoz.cjb.net
Non sempre quello che viene dopo e` progresso.
Alessandro Manzoni