El módulo es un contador, y las funciones de lectura y escritura son la suma del contador y la consulta del número actual. Su escritura sólo suma si todo va bien, y su lectura devuelve en el buffer del usuario la copia del valor. El problema es que al hacer el makefile del módulo recibo el error:
Citar
"insmod: error inserting 'ModuloUsaKifs.ko': -1 Unknown symbol in module"
Y no sé exáctamente por qué no reconoce Kifs, que según creo, está integrado en el sistema correctamente (Incluidas las fuentes, modificado el planificador, añadido a la tabla de llamadas, incluida la cabecera, compilado el kernel, instalado el nuevo, y probado con un programa aparte, aunque sólo pruebo sys_kifs, mi llamada al sistema, exporto también create_kifs_entry y remove_kifs_entry mediante <linux/kifs.h>)
Este es mi makefile, es muy estándar y no contemplo nada especial, porque se supone que kifs ya está en las fuentes de linux y así lo incluyo en el módulo.
¿Podría alguien orientarme hacia dónde está mi fallo?
Citar
obj-m = ModuloUsaKifs.o
all :
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean :
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
all :
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean :
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Este es el módulo. Siento la falta de comentarios, todavía no lo he acabado y está un poco guarro(Esto es como tener visita con la casa sucia) Tengo algunos includes de más porque aún no los he borrado, he reutilizado algo de código de aquí y allá.
Código
#ifdef __KERNEL__ #include <linux/module.h> #include <linux/kernel.h> #include <linux/proc_fs.h> #include <linux/string.h> #include <linux/vmalloc.h> #include <linux/kifs.h> #include <asm-generic/uaccess.h> MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("List Kernel Module para DSO"); MODULE_LICENSE("GPL"); #else //#include <iostream> //#include <linux/list.h> #include <string.h> #include "list.h" #include <stdio.h> #include <stdlib.h> #include "kifs.h" #endif int counter; //typedef int (read_kifs_t)(char *user_buffer, unsigned int maxchars, void *data); //typedef int (write_kifs_t)(const char *user_buffer, unsigned int maxchars, void *data); //initialices the module int sum(char *user_buffer, unsigned int maxchars, void *data){ counter++; return maxchars; } int lect(const char *user_buffer, unsigned int maxchars, void *data){ char buf[32]; if (len> maxchars) { return -EINVAL; } if(copy_to_user(buf, user_buffer, len)){ printk(KERN_ALERT) "problemas en lect"; return -EINVAL; } return len; } int metodoInicial(void){ counter = 0; if(create_kifs_entry("counter",sum,lect,NULL)) { counter = 0; printk(KERNEL_ALERT "modulo abierto correctamente"); } printk(KERNEL_ALERT "Error, módulo counter incorrectamente agregado a kifs"); } void metodoFinal(void){ if(remove_kifs_entry("counter")){ printk(KERNEL_ALERT "modulo cerrado correctamente"); } printk(KERNEL_ALERT "Error, módulo counter incorrectamente borrado de kifs"); } module_init(metodoInicial); module_exit(metodoFinal);
Esta es la llamada al sistema, por si pudiese ser algo relacionado con esto, sinceramente ya no sé qué puede ser porque me estoy volviendo loco.
Código
#include <linux/kifs.h> #include <linux/string.h> #include <linux/module.h> #include <linux/kernel.h> #include <asm-generic/errno-base.h> #include <asm-generic/errno.h> #include <asm-generic/uaccess.h> /* MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Modulo KIFS para DSO"); MODULE_AUTHOR("Ismel Gonjal Montero"); */ /* Callback prototypes for kifs entries */ /* typedef int (read_kifs_t)(char *user_buffer, unsigned int maxchars, void *data); typedef int (write_kifs_t)(const char *user_buffer, unsigned int maxchars, void *data); */ /* Valores de lectura y escritura */ /* enum { KIFS_READ_OP=0, KIFS_WRITE_OP, KIFS_NR_OPS}; */ /***********************************/ /* Declaraciones de kifs */ /***********************************/ #define MAX_KIFS_ENTRIES 10 LIST_HEAD(entry_list); LIST_HEAD(free_list); kifs_entry_t pool[MAX_KIFS_ENTRIES]; /***********************************/ /* Declaraciones de clipboard */ /***********************************/ #define MAX_KIFS_CHARS 512 char clipboard[MAX_KIFS_CHARS]; /************************************/ /* Declaracion de funciones */ /************************************/ int read_list (char *user_buffer, unsigned int maxchars, void *data); /******************************************************************************/ /* CLIPBOARD */ /******************************************************************************/ int read_clipboard (char *user_buffer, unsigned int maxchars, void *data){ if (total>maxchars) { return -EINVAL; } if (copy_to_user(user_buffer, clipboard, total)) { printk(KERN_ALERT "Fallo en copy_to_user()"); return -EINVAL; } return total; } int write_clipboard (const char *user_buffer, unsigned int maxchars, void *data){ if (maxchars>MAX_KIFS_CHARS-1) { printk(KERN_ALERT "Excede tamanio"); return -EINVAL; } if (copy_from_user(clipboard, user_buffer, maxchars)) { printk(KERN_ALERT "Fallo en copy_from_user()"); return -EINVAL; } clipboard[maxchars]='\0'; return maxchars; } /****************************************************/ /* Código de KIFS */ /****************************************************/ /* KIFS's global initialization */ void init_kifs_entry_set(void){ int i = 0; //añade a la lista todas las entradas de freelist for(i =0; i<MAX_KIFS_ENTRIES;i++){ list_add_tail(&pool[i].links,&free_list); } clipboard[0]='\0'; create_kifs_entry("list", read_list,NULL,NULL); create_kifs_entry("clipboard", read_clipboard,write_clipboard ,NULL); printk(KERN_ALERT "Inicializado kifs"); } /* * Recibe un buffer de usuario, que llenará con una lista de las entradas * de la lista entry_list */ int read_list (char *user_buffer, unsigned int maxchars, void *data){ int total = 0; char buf[512]; struct list_head* pos = entry_list.next; kifs_entry_t* item; printk(KERN_ALERT "Entra en read_list"); list_for_each(pos, &entry_list){ item = list_entry(pos, kifs_entry_t, links); } if (copy_to_user(user_buffer,buf,total)) { printk(KERN_ALERT "Fallo en copy_to_user()"); return -EINVAL; } printk(KERN_ALERT "Sale de read_list por las buenas"); return total; } /* This fuction must ensure that no entry will be created as long as another entry with the same name already exists. * == Return Value == * NULL Entry name already exists or No space is availables * Pointer to the kifs entry * */ kifs_entry_t* create_kifs_entry(const char* entryname, read_kifs_t *read_kifs, write_kifs_t *write_kifs, void* data){ kifs_entry_t* item; struct list_head* pos = entry_list.next; kifs_entry_t* itemFound = NULL; printk(KERN_ALERT "Creando entrada %s en Kifs",entryname); //Si la lista no está vacía list_for_each(pos, &entry_list){ item = list_entry(pos, kifs_entry_t, links); itemFound = item; break; } } if (itemFound != NULL) { printk(KERN_ALERT "El item existe"); return NULL; } //No hay espacio if(free_list.next == &free_list) { printk(KERN_ALERT "Error, lista llena"); return NULL; } pos = free_list.next; item = list_entry(pos, kifs_entry_t, links); item->read_kifs = read_kifs; item->write_kifs = write_kifs; item->data = NULL; list_del(pos); list_add_tail(pos,&entry_list); printk(KERN_ALERT "Entrada %s creada correctamente", entryname); return item; } /* Implementation of kifs() system call * == Return Value == * -EINVAL Unsupported operation (NULL callback) or Entry not exists * -EFAULT Any other error (e.g: copy_from_user(), copy_to_user(),...) * otherwise: Number of chars read/written (Usually maxchars value) */ asmlinkage long sys_kifs(const char* entry_name,unsigned int op_mode, char* user_buffer,unsigned int maxchars){ struct list_head* pos;// = entry_list.next; kifs_entry_t* item;// = list_entry(pos, kifs_entry_t, links); kifs_entry_t* itemFound = NULL; int ret = 0; //char usrBfr[512]; printk(KERN_ALERT "Entrado a sys_kifs"); /* Se comprueba que la llamada has sido correcta */ list_for_each(pos, &entry_list){ item = list_entry(pos, kifs_entry_t, links); itemFound = item; break; } } if (itemFound == NULL){ printk(KERN_ALERT "La entrada %s no existe", entry_name); return -EINVAL; } /* copy_from_user(usrBfr, user_buffer, maxchars); usrBfr[maxchars]='\0'; printk(KERN_ALERT "Se ha copiado el parametro %s de la entrada %s",usrBfr, entry_name); printk(KERN_ALERT "Hay items en la lista"); */ /* llamadas que dependen del valor de lectura/escritura */ if(op_mode == KIFS_READ_OP && item->read_kifs!=NULL ){ ret = itemFound->read_kifs(user_buffer,maxchars,NULL); //printk(KERN_ALERT "El item utilizado es %s, en el método de lectura",user_buffer); }else if(op_mode == KIFS_WRITE_OP && item->write_kifs!=NULL ){ ret = itemFound->write_kifs(user_buffer,maxchars,NULL); //No sé qué pasar de valor aquí //printk(KERN_ALERT "El item utilizado es %s, en el método de escritura",usrBfr); }else{ ret=-EINVAL; printk(KERN_ALERT "Algo va mal"); } return ret; } /* Remove kifs entry * == Return Value == * -1 Entry does not exist * 0 success * */ int remove_kifs_entry(const char* entry_name){ struct list_head* pos = entry_list.next; kifs_entry_t* item = list_entry(pos, kifs_entry_t, links); kifs_entry_t* itemFound = NULL; printk(KERN_ALERT "Intentando eliminar entrada de Kifs"); list_for_each(pos, &entry_list){ item = list_entry(pos, kifs_entry_t, links); itemFound = item; break; } } if (itemFound == NULL) { printk(KERN_ALERT "La lista de kifs está vacía"); return -EINVAL; } list_del(pos); item->data = NULL; item->read_kifs = NULL; item->write_kifs = NULL; list_add_tail(pos,&free_list); printk(KERN_ALERT "Entrada eliminada correctamente"); return 0; }
Y por si acaso también subo el .h de kifs, mi llamada al sistema.
Código
#ifndef KIFS_H #define KIFS_H #include <linux/list.h> /* list_head */ #define MAX_KIFS_ENTRY_NAME_SIZE 50 /* Callback prototypes for kifs entries */ typedef int (read_kifs_t)(char *user_buffer, unsigned int maxchars, void *data); typedef int (write_kifs_t)(const char *user_buffer, unsigned int maxchars, void *data); /* Descriptor interface for the entries */ typedef struct { char entryname[MAX_KIFS_ENTRY_NAME_SIZE]; read_kifs_t *read_kifs; write_kifs_t *write_kifs; void *data; struct list_head links; /* Set of links in kifs */ }kifs_entry_t; enum { KIFS_READ_OP=0, KIFS_WRITE_OP, KIFS_NR_OPS}; /* This fuction must ensure that no entry will be created as long as another entry with the same name already exists. * == Return Value == * NULL Entry name already exists or No space is availables * Pointer to the kifs entry * */ kifs_entry_t* create_kifs_entry(const char* entryname, read_kifs_t *read_kifs, write_kifs_t *write_kifs, void* data); /* Remove kifs entry * == Return Value == * -1 Entry does not exist * 0 success * */ int remove_kifs_entry(const char* entry_name); /* Implementation of kifs() system call * == Return Value == * -EINVAL Unsupported operation (NULL callback) or Entry not exists * -EFAULT Any other error (e.g: copy_from_user(), copy_to_user(),...) * otherwise: Number of chars read/written (Usually maxchars value) */ asmlinkage long sys_kifs(const char* entry_name,unsigned int op_mode, char* user_buffer,unsigned int maxchars); /* KIFS's global initialization */ void init_kifs_entry_set(void); #endif
Muchas gracias por vuestro tiempo
Para ser concretos el mensaje del sistema es:
Citar
make -C /lib/modules/2.6.39.4.mikernel/build M=/home/dsouser/Escritorio/FuturaEntrega/ModuloUsaKifs modules
make[1]: se ingresa al directorio `/usr/src/linux-headers-2.6.39.4.mikernel'
Building modules, stage 2.
MODPOST 1 modules
WARNING: "create_kifs_entry" [/home/dsouser/Escritorio/FuturaEntrega/ModuloUsaKifs/ModuloUsaKifs.ko] undefined!
WARNING: "remove_kifs_entry" [/home/dsouser/Escritorio/FuturaEntrega/ModuloUsaKifs/ModuloUsaKifs.ko] undefined!
make[1]: se sale del directorio `/usr/src/linux-headers-2.6.39.4.mikernel'