我是stackoverflow的新手,至少作为一个提问者。首先,我想为我的拼写语言道歉,因为这不是我的母语,坦率地说,我已经忘记了很久了。
我正在为Debian 6(内核2.6.39.4)编写内核模块,该模块与我对系统的调用进行交互。它们都很简单,因为我是在学习目的。 Syscall看起来像是在工作,并向用户输出一个功能,允许插入一个条目列表并注册这两个函数,一个读取,另一个写入。
模块只是一个计数器,其读写功能是计数器值的补充和当前计数器值的参考。如果一切正常,则写入函数会向计数器添加一个,并且read函数会将计数器返回给缓冲区。当我使用makefile时会出现问题,然后我收到这条消息(西班牙语中的所有内容都被字面翻译)
make -C /lib/modules/2.6.39.4.mikernel/build M=/home/dsouser/Escritorio/FuturaEntrega/ModuloUsaKifs modules
make[1]: acess to the directory `/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]: get out of the directory `/usr/src/linux-headers-2.6.39.4.mikernel'
我不知道为什么不支持创建和删除功能。 “kifs”系统调用是(我认为)正确实现的(包括.h和.c,修改了调度,添加到syscall表,内核编译,调试,并用程序测试)我只证明了“sys_kifs”系统调用,但不是.h函数。这是我使用的makefile。
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
这就是模块。我很抱歉缺少文档,因为内核消息是西班牙语。我觉得人们进入我未清洁的厕所。我有一些额外的包括我将在以后删除。 ModuloUsaKifs.c
#define PROC_ENTRY "mymodule"
#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/string.h>
#include <linux/kifs.h>
#include <asm-generic/errno-base.h>
#include <asm-generic/errno.h>
#include <asm-generic/uaccess.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("List Kernel Module para DSO");
MODULE_AUTHOR("Kaostias");
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);
/**********************/
/* módulo en sí mismo */
/**********************/
int sum(char *user_buffer, unsigned int maxchars, void *data){
char str [256];
if (copy_from_user(str, user_buffer, maxchars)) {
return -EFAULT;
}
counter++;
return maxchars;
}
int lect(const char *user_buffer, unsigned int maxchars, void *data){
char buf[32];
int len=sprintf(buf,"%d\n",counter);
if (len> maxchars)
{
return -EINVAL;
}
if(copy_to_user(buf, user_buffer, len)){
printk(KERN_INFO "problemas en lect");
return -EINVAL;
}
return len;
}
int metodoInicial(void){
counter = 0;
if(create_kifs_entry("counter",sum,lect,NULL) != NULL)
{
counter = 0;
printk(KERN_INFO "modulo abierto correctamente");
return 0;
}
printk(KERN_INFO "Error, módulo counter incorrectamente agregado a kifs");
return -EINVAL;
}
void metodoFinal(void){
if(remove_kifs_entry("counter")){
printk(KERN_INFO "modulo cerrado correctamente");
}
printk(KERN_INFO "Error, módulo counter incorrectamente borrado de kifs");
}
/*********************************/
/* Registra el init y el cleanup */
/*********************************/
module_init(metodoInicial);
module_exit(metodoFinal);
这是“kifs”的标题
#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 function 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
这是kifs.c本身
//#include "list.h"
#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){
int total = strlen(clipboard);
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);
total+= sprintf(&buf[total],"%s\n",item->entryname);
}
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 function 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);
if (strcmp(item->entryname,entryname) ==0){
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;
strcpy(item->entryname, entryname);
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);
if (strcmp(item->entryname,entry_name) ==0){
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);
if (strcmp(item->entryname,entry_name) ==0){
itemFound = item;
break;
}
}
if (itemFound == NULL) {
printk(KERN_ALERT "La lista de kifs está vacía");
return -EINVAL;
}
list_del(pos);
item->data = NULL;
strcpy(item->entryname,"");
item->read_kifs = NULL;
item->write_kifs = NULL;
list_add_tail(pos,&free_list);
printk(KERN_ALERT "Entrada eliminada correctamente");
return 0;
}
如果有必要将dmesg的结果与此问题联系起来
[ 1818.076342] ModuloUsaKifs: Unknown symbol remove_kifs_entry (err 0)
[ 1818.076590] ModuloUsaKifs: Unknown symbol create_kifs_entry (err 0)
答案 0 :(得分:1)
从评论到问题:
您需要使用EXPORT_SYMBOL导出函数名称,以便内核的其他部分调用这些函数。导出这些符号将在符号表中创建一个条目,从中查找其他模块/内核代码。如果只有您的模块使用这些功能,则无需导出。
在您的情况下,这些函数在一个模块中定义,并在另一个模块中使用。所以:
只需添加EXPORT_SYMBOL(create_kifs_entry);和EXPORT_SYMBOL(remove_kifs_entry);到你的代码