- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我是 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/
在 python 交互中,有没有办法在每次输入命令后自动从 python 文件执行方法? 例如:如果我有一个打印文件信息的方法,但我不想不断调用该方法,我怎样才能让它在 python 交互中的每个命令
当你使用Edge等浏览器或系统软件播放媒体时,Windows控制中心就会出现相应的媒体信息以及控制播放的功能,如图。 SMTC (SystemMedia
我在主菜单上使用标准的剪切,复制,粘贴操作。它们具有快捷键Ctrl-X,Ctrl-C和Ctrl-V。 当我打开模态表单时FindFilesForm.ShowModal,然后所有快捷方式都可以从表单中使
这是我想要实现的目标:打开一个 shell(korn 或 bash,没关系),从那个 shell,我想打开一个 ssh 连接(ssh user@host)。在某些时候,可能会提示我输入密码,或者可能会
我正在测试在C / C++程序中嵌入Python,但是我缺乏理解。 测试程序很简单: 初始化解释器; 从启动Timer的文件中执行python脚本(每0.1秒增加一个变量); 等待5秒(C++); 从
我正在尝试用java创建Excel文件。现在,我正在使用 Apache POI 库创建文件并将其保存到本地驱动器。有没有办法启动 Excel 并填充数据而不将其保存到硬盘驱动器? 最佳答案 考虑 Do
我有一个黑盒函数,它接受大约 10 个整数输入。该函数返回一个 pandas 数据框,我想捕获输出窗口(通过使用 bbwidget.children)并显示在布局中的其他地方。到目前为止,交互/交互似
我正在体验新的 QQuickWidget。我如何在 QQuickWidget 和 C++ 之间进行交互? C++ QQuickWidget *view = new QQuickWidget(); vi
我正在尝试设置一个使用 TWAIN 的 C# 应用程序 example from code project 除了我需要将 Form 转换为 IMessageFilter 和调用 IMessageFil
我想在使用 redis 的 python 中编写应用程序。我用谷歌搜索,但找不到我的问题的任何结果。通常,我这样做: import redis rs = redis.Redis('localhost'
最近做一个小项目,网页中嵌入google maps,输入经纬度坐标可以定位地图位置并加注标记,点击标记获取远端摄像头数据并在视频窗口实现播放。在实际操作过程中,由于经纬度数据和视频登录的用户名密码数
我需要在这里澄清一些事情: 我有一个网站,每次在浏览器中重新加载网站时都会更新两个变量的值。这个页面显然是一个 HTML 页面,但变量是由 javascript 函数更新的。此页面在我的服务器上运行。
我注意到,auto忽略双条件。这是一个简化的示例: Parameter A B : Prop. Parameter A_iff_B : A B. Theorem foo1: A -> B. Proo
使用 interactive使用多个小部件相当简单,例如: interactive(foo, w1=widget1, w2=widget2, ...) 但是,我想使用 VBox 和 HBox 的组合以
我们提供类似于 imagemagick 的浏览器页面 JavaScript,可帮助人们将图像转换为不同大小和格式。但是,它需要网页交互。 是否可以让人们自动进行这种交互——无需将图像发送到我们的服务器
大家好,我正在尝试制作一个具有大量动画和效果的交互式 UI。 但我不知道是否: 核心图形可以支持用户交互(触摸、拖动等) 核心图形支持对象旋转 核心图形可以以任何方式与 UIKit 和核心动画交互 谢
这是获取维基百科上一篇关于高盛的文章的介绍的链接。 http://en.wikipedia.org/w/api.php?action=query&prop=extracts&titles=Goldma
我正在尝试编写一个 AppleScript 来查询 iCal 并在任何日历中查找给定日期的所有事件。 我首先编写了一个简单的脚本,它对给定日历中的每个事件执行一些简单的操作: tell applica
我在我的 hudson 服务器上使用 jira 插件。将代码提交到 svn 时,我的提交注释包含在我的 jira 问题中,但有什么办法可以将注释归因于执行提交的实际人员,而不是让一个全局 jira 用
我正在播放一段视频来装饰我的用户界面。我隐藏了 AV 播放器控件,但用户仍然可以控制视频。例如,他们可以使用滑动手势快进或快退。 这让我特别惊讶,因为 AVPlayerView 上面有一个覆盖 Vie
我是一名优秀的程序员,十分优秀!