gpt4 book ai didi

c - 内核模块与 sys_call 交互

转载 作者:太空狗 更新时间:2023-10-29 12:33:21 29 4
gpt4 key购买 nike

我是 stackoverflow 的新手,至少作为提问者是这样。首先,我要为我的拼写道歉,因为这不是我的母语,坦率地说,我已经忘记了很长时间。

我正在为 Debian 6(内核 2.6.39.4)编写一个内核模块,它与我对系统的调用进行交互。它们都很容易,因为我这样做是为了学习。系统调用看起来像是在工作,并向用户导出一项功能,该功能允许插入条目列表并在这两个函数中注册,一个用于读取,另一个用于写入。

模块只是一个计数器,其读写功能是对计数器值的加法和对当前计数器值的查询。如果一切正常,写入函数将计数器加一,读取函数将计数器返回给用户,放入缓冲区。问题发生在我使用 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 函数。这是我使用的生成文件。

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)

最佳答案

从评论到问题:

您需要使用 EXPORT_SYMBOL 导出函数名,以便内核的其他部分调用这些函数。导出这些符号将在符号表中创建一个条目,其他模块/内核代码从中查找它们。如果只有您的模块使用这些函数,则不需要导出。

在您的例子中,这些函数在一个模块中定义并在另一个模块中使用。所以:

只需添加 EXPORT_SYMBOL(create_kifs_entry);和 EXPORT_SYMBOL(remove_kifs_entry);到你的代码

关于c - 内核模块与 sys_call 交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20338892/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com