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.