增加Linux系统调用——通过增加内核模块

在上一篇日志《增加Linux系统调用——通过重新编译内核》中已经介绍了如何通过编译Linux内核的方式来增加系统调用。这里将继续介绍如何通过增加内核模块的方式增加Linux系统调用。

●添加系统调用的入口参数

#define __NR_zzr_callmod 336

●在linux-2.6.30.6/arch/x86/kernel/syscall_table_32.S 中添加:.long sys_zzr_callmod /* 336 */

.long sys_zzr_callmod /* 336 */

●添加自定义系统响应函数

修改linux-2.6.30.6/kernel/sys.c文件,在文件末尾添加自定义的系统响应函数。函数实现如下:

/*	The function point that is used to call system module 
	Added by ZZR				                  */
int (*zzr_function)(int *, int, int, char) = NULL;	//函数指针
EXPORT_SYMBOL_GPL(zzr_function);
asmlinkage int sys_zzr_callmod(int *result, int first, int second, char op)//模块调用函数
{
	if(zzr_function){
		return zzr_function(result,first,second,op);
	}
}

在sys_zzr_callmod之前定义与要调用的外部模块中函数同类型的函数指针zzr_function,并且把zzr_function通过EXPORT_SYMBOL_GPL放到内核全局符号表中

注:EXPORT_SYMBOL(符号名);EXPORT_SYMBOL_GPL(符号名); //只有包含GPL许可权的模块才可以访问该符号名

编写内核模块代码

新建文件夹放置内核模块代码和Makefile文件。

内核模块代码testmodule.c:

#include <linux/kernel.h>
#include <linux/module.h>

MODULE_LICENSE("GPL");  

extern int (*zzr_function)(int *, int, int, char);	//函数指针
int my_function_module(int *result, int first, int second, char op){
	printk("In the kernel module\n");
	switch(op){
		case '+': *result = first + second; break;
		case '-': *result = first - second; break;
		case '*': *result = first * second; break;
		case '/':
			if(second == 0){
				printk("divisor can't be 0.\n");
				return -1;
			}		
			*result = first / second; break;
		default:
			printk("operator is illegal.\n");
			return -1;
	}
	return 0;
}

static int my_init(void)  
{  
	zzr_function = my_function_module;
    printk("ZZR_module_init success!\n");  
    return 0;  
} 

static int my_exit(void)  
{  
    printk("ZZR_module_exit success!\n");  
    return 0;  
}  

module_init(my_init);  
module_exit(my_exit);  
Makefie文件:

ifneq ($(KERNELRELEASE),)
	obj-m := testmodule.o
else
	KERNEL_VER := $(shell uname -r)
	KERNEL_DIR := /lib/modules/$(KERNEL_VER)/build 
	CUR_PATH := $(shell pwd) 

default:
	$(MAKE) -C $(KERNEL_DIR) M=$(CUR_PATH) modules
modules_install:
	$(MAKE) -C $(KERNEL_DIR) M=$(CUR_PATH) modules_install
clean:
	$(MAKE) -C $(KERNEL_DIR) M=$(CUR_PATH) clean
endif
注意testmodule.o文件的名字必须与内核模块代码的文件名相同。

编译内核模块

$ make


$ insmod testmodule.ko插入内核模块

$ lsmod 查看目前已经加载的内核模块


编写测试代码

#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <time.h>
#define __NR_zzr_calculator 335
#define __NR_zzr_callmod 336


int main(){
	clock_t start,finish;
	double duration1,duration2;
	start = clock();
	int result;
	syscall(__NR_zzr_callmod,&result,3,4,'+');
	printf("+:\t%d\n",result);
	syscall(__NR_zzr_callmod,&result,3,4,'-');
	printf("-:\t%d\n",result);
	syscall(__NR_zzr_callmod,&result,3,4,'*');
	printf("*:\t%d\n",result);
	syscall(__NR_zzr_callmod,&result,3,4,'/');
	printf("/:\t%d\n",result);
	finish = clock();
	duration1 = (double)(finish-start)/CLOCKS_PER_SEC;	
	printf("Kernel:\t%f\n",duration1);
	return 0;
}
程序运行结果与增加Linux系统调用——通过重新编译内核》完全相同,实验成功。

这里要注意的是,事实上,虽然可以动态地修改内核模块代码,但是最开始的时候还是要通过编译内核来增加函数指针,通过这个函数指针来调用内核模块。也就是说,这个函数指针的形式事实上已经固定了,这也就限制了内核模块函数的形式。这种动态加载并不是完全的自由。



  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值