c linux-kernel linux-device-driver

función cat llamando a read() infinitas veces



linux-kernel linux-device-driver (3)

Estoy trabajando en un controlador de dispositivo de caracteres simple. He implementado funciones de lectura y escritura en el módulo, el problema es que cuando trato de leer el archivo del dispositivo usando cat /dev/devicefile , entra en un bucle infinito, es decir, lee los mismos datos repetidamente. ¿Alguien puede sugerirme alguna solución a este problema? A continuación se muestra mi código de conductor.

#include<linux/module.h> #include<linux/fs.h> #include<linux/string.h> #include<asm/uaccess.h> #include<linux/init.h> MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("character device driver"); MODULE_AUTHOR("Srinivas"); static char msg[100]={0}; static int t; static int dev_open(struct inode *, struct file *); static int dev_rls(struct inode *, struct file *); static ssize_t dev_read(struct file *, char *,size_t, loff_t *); static ssize_t dev_write(struct file *, const char *, size_t,loff_t *); static struct file_operations fops = { .read = dev_read, .open = dev_open, .write = dev_write, .release = dev_rls, }; static int himodule( void ) { t = 0; t = register_chrdev(0, "chardevdriver", &fops); if (t < 0) printk(KERN_ALERT"device registration failed/n"); else printk(KERN_ALERT"device registered successfully/n"); printk(KERN_ALERT"major number is %d", t); return 0; } static void byemodule(void) { unregister_chrdev(t, "chardevdriver"); printk(KERN_ALERT"successfully unregistered/n"); } static int dev_open(struct inode *inod, struct file *fil) { printk(KERN_ALERT"inside the dev open"); return 0; } static ssize_t dev_read(struct file *filp, char *buff, size_t len, loff_t *off) { short count = 0; while (msg[count] != 0) { put_user(msg[count], buff++); count++; } return count; } static ssize_t dev_write(struct file *filp, const char *buff, size_t len, loff_t *off) { short count = 0; printk(KERN_ALERT"inside write/n"); memset(msg,0,100); printk(KERN_ALERT" size of len is %zd",len); while (len > 0) { msg[count] = buff[count]; len--; count++; } return count; } static int dev_rls(struct inode *inod,struct file *fil) { printk(KERN_ALERT"device closed/n"); return 0; } module_init(himodule); module_exit(byemodule);


Este problema se puede resolver configurando correctamente *off (cuarto parámetro de my_read() ).

Debe devolver el recuento por primera vez y cero a partir de la segunda vez.

if(*off == 0) { while (msg[count] != 0) { put_user(msg[count], buff++); count++; (*off)++; } return count; } else return 0;


No respeta el tamaño del búfer pasado a la función dev_read , por lo que puede invocar un comportamiento indefinido en cat . Prueba esto:

static ssize_t dev_read( struct file *filp, char *buff, size_t len, loff_t *off ) { size_t count = 0; printk( KERN_ALERT"inside read %d/n", *off ); while( msg[count] != 0 && count < len ) { put_user( msg[count], buff++ ); count++; } return count; }


.read función .read también debe procesar correctamente sus argumentos len y off . La forma más sencilla de implementar la lectura del archivo con memoria intermedia es usar el ayudante simple_read_from_buffer :

static ssize_t dev_read(struct file *filp, char *buff, size_t len, loff_t *off) { return simple_read_from_buffer(buff, len, off, msg, 100); }

Puede inspeccionar el código de ese ayudante (definido en fs/libfs.c ) con fines educativos.

Por cierto, para su método .write podría usar simple_write_to_buffer helper.