【发布时间】:2013-12-18 18:52:37
【问题描述】:
我是 stackoverflow 的新手,至少作为提问者。首先我要为我的拼写道歉,因为这不是我的母语,坦率地说我已经忘记了很长时间。
我正在为 Debian 6(内核 2.6.39.4)编写一个内核模块,该模块与我对系统的调用进行交互。它们都很容易,因为我这样做是出于学习目的。 Syscall 看起来正在工作,并向用户导出一项功能,该功能允许插入条目列表并在这两个函数中注册,一个读取,另一个写入。
模块只是一个计数器,它的读写功能是对计数器值的补充和对当前计数器值的查询。如果一切正常,写入函数将计数器加一,读取函数将计数器返回给用户并放入缓冲区。问题发生在我使用 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,修改了时间表,添加到系统调用表,编译内核,安装,并用程序测试)我只证明了“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
这就是模块。我很抱歉缺少文档,因为内核消息是西班牙语的。我觉得有人进入我未清洁的厕所。我有一些额外的内容,稍后会删除。模UsaKifs.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)
【问题讨论】:
-
将
EXPORT_SYMBOL(create_kifs_entry);和EXPORT_SYMBOL(remove_kifs_entry);添加到您的kifs.c。这会将符号添加到a table that allows fix-ups when a module is loaded。 -
谢谢,成功了!现在我有另一个问题,但我会自己解决。我对这个问题感到非常生气。
-
@Kaostias 您能否为后代回答您自己的问题?
-
答案就在这里,我刚刚在我的代码中添加了
EXPORT_SYMBOL(create_kifs_entry);和EXPORT_SYMBOL(remove_kifs_entry);
标签: c linux linux-kernel system-calls