内核模块编程基础

1、应用程序与内核模块

内核模块可以看做内核程序的一部分,类似于Window下的补丁,但安装比补丁方便,可在内核运行时安装与卸载


(1)应用程序:man函数的return执行完后则应用程序退出,释放内存
(2)内核模块:安装完成后就驻留在系统内存中


2、程序结构

(1)#include <linux/module.h>

         #include <linux/init.h>
(2)模块加载函数 —— 必需
     module_init宏
安装内核模块时调用内核模块加载函数
而应用程序的main函数则在运行时调用
(3)模块卸载函数 —— 必需
     module_exit宏
卸载内核模块时调用
应用程序返回时使用return

  (4)可选项
[1]许可证声明 MODULE_LICENSE("GPL");
[2]作者声明   MODULE_AURHOE("monkeyzx");
[3]模块描述   MODULE_DESCRITION("Helloworld module");
[4]模块版本   MODULE_VERSION("V1.0");
[5]模块别名   MODULE_ALIAS("SimpleHW");

[6]模块参数
格式   module_param(name[参数名称], type[参数类型], perm[访问权限]);
type: bool[布尔型]/int[整形]/charp[字符型]
perm: S_IRUGO[读权限]/S_IWUSR[读权限]
注意:模块参数使用前需要像应用程序一样声明,
      但char*类型不需要使用类似malloc的函数分配空间

3、内核程序编译 —— 使用makefile

下面的makefile可以用作模板

################################################################
ifneq ($(KERNELRELEASE),)
obj-m := mymodule.o  #模块名
#一个模块包含多文件,file1.o file2.o file3.o 属于同一个模块
mymodule-objs := file1.o file2.o file3.o # 若要同时编译多个模块,参考下面的代码实例
# obj-m:= module1.o module2.o ...elseKDIR := /lib/modules/2.6.18-53.el5/build 
#定义变量KDIR,内核代码路径all: make -C $(KDIR) M=$(PWD) modules 
#-C选项 指定路径
clean: rm -f *.ko *.o *.mod.c *.symers endif
################################################################


4、安装与卸载内核模块
(1)
先切换到命令行模式Ctrl+Alt+空格+F1~6
使用root用户登录
返回图形界面使用Ctrl+Alt+空格+F7
(2)
insmod <module>.ko 安装过程调用模块安装函数
rmmod <module>     
lsmod 查看已经安装的内核模块
modprobe <module>.ko 安装模块(会检查模块依赖关系)


5、内核符号导出
(1)当模块A需要调用模块B中定义的函数时,2件事要做
   [a]需要将函数从另一个模块中导出 
      EXPORT_SYMBOL("符号名/函数名")
      EXPORT_SYMBOL_GPL("符号名/函数名")
   [b]先insmod模块B在insmod模块A
   
(2)如何查看系统中已有的Symbol信息
/proc/callsyms中记录了所有导出的符号的名字与地址,
因此可以通过cat /proc/callsyms查看系统中所有导出的符号


6、打印函数
(1)类比:内核模块中使用printk打印,而应用程序中使用printf
(2)区别:prink打印存在“优先级”,通过“优先级”对消息分类
   优先级定义在<linux/kernel.h>,默认优先级为KERN_WARNING
   KERN_EMERG   <0>
   KERN_ALERT   <1>
   KERN_CRIT    <2>
   KERN_ERR     <3>
   KERN_WARNING <4>
   KERN_NOTICE  <5>
   KERN_INFO    <6>
   KERN_DEBUG   <7>
   因为控制台也有优先级(优先级为6),
   因此只有pritk中优先级比<6>小(高)的时候才能在控制台打印信息
 
7、内核模块编程实例
"ex_mod.c"

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

MODULE_LICENSE("GPL");
MODULE_AUTHOR("monkeyzx");
MODULE_DESCRIPTION("A sample example of export symbol");
MODULE_VERSION("V1.0");

int a = 3;
int b = 5;
module_param(a, int, S_IWUSR|S_IRUGO);
module_param(b, int, S_IWUSR|S_IRUGO);

extern int add(int x, int y);
extern int sub(int x, int y);

static int __init ex_mod_init()
{
	int res = add(a, b);
	printk(KERN_NOTICE"add=%d\n", res);

	return 0;
}

static void __exit ex_mod_exit()
{
	int res = sub(a, b);

	printk(KERN_NOTICE"sub=%d\n", res); 
}

module_init(ex_mod_init);
module_exit(ex_mod_exit);

"cal.c"

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

MODULE_LICENSE("GPL");
MODULE_AUTHOR("monkeyzx");
MODULE_DESCRIPTION("Caculation");
MODULE_VERSION("V1.0");

int add(int x, int y)
{
	return (x+y);
}

int sub(int x, int y)
{
	return (x-y);
}


static int __init cal_init()
{
	return 0;
}

static void __exit cal_exit()
{
	
}

module_init(cal_init);
module_exit(cal_exit);

//export symbols
EXPORT_SYMBOL(add);
EXPORT_SYMBOL(sub);

使用makefile编译,makefile内容如下
#####################################################################
ifneq ($(KERNELRELEASE),)
obj-m := ex_mod.o cal.o
else
KDIR := /lib/modules/2.6.18-53.el5/build
all:
 make -C $(KDIR) M=$(PWD) modules
clean:
 rm -f *.ko *.o *.mod.o *.mod.c *.symvers
endif
###################################################################### 
在SHELL中运行
make
insmod cal.ko                 
insmod ex_mod a=10 b=8              (结果为add=18)
rmmod ex_mod                              (结果为sub=2)
rmmod cal
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值