一、内核模块基础
1.1 什么是内核模块
Linux内核的整体结构非常庞大,其包含的组件也非常
多,如何使用这些组件呢, 方法1:把所有的组件都编
方法1:把所有的组件都编
译进内核文件,即:zImage或bzImage,但这样会导
致一个问题:占用内存过多.
有没有一种机制能让内核文件本身并不包含某组件,而
是在该组件需要被使用的时候,动态地添加到正在运行
的内核中呢?
1.2 内核模块特点
①模块本身并
不被编译进内核文件
(zImage或者bzImage)
②可以更具需求,
在内核运行期间动态的安装或卸载
。
1.3 内核安装与卸载
安装 insmod
例:insmod /hoem/dnw_usb.ko
卸载rmmod
例:rmmod dnw_usb
查看 lsmod
例:lsmod
二、内核模块设计
2.1 内核的
三要素:
头文件:linux/init.h linux/module.h
insmod,运行模块入口:module_init();
rmmod,运行模块退出:module_exit();
2.2 内核的思维导图
2.3 内核的helloworld编写
#include <linux/init.h> #include <linux/module.h> static int hello_init(void) { printk(KERN_WARNING"Hello, world !\n"); return 0; } static void hello_exit(void) { printk(KERN_INFO "Goodbye, world\n"); } module_init(hello_init); module_exit(hello_exit);
printk
日志级别一共有8个级别,printk的日志级别定义如下(在
include/linux/kernel.h
中):
#define KERN_EMERG 0/*紧急事件消息,系统崩溃之前提示,表示系统不可用*/
#define KERN_ALERT 1/*报告消息,表示必须立即采取措施*/
#define KERN_CRIT 2/*临界条件,通常涉及严重的硬件或软件操作失败*/
#define KERN_ERR 3/*错误条件,驱动程序常用KERN_ERR来报告硬件的错误*/
#define KERN_WARNING 4/*警告条件,对可能出现问题的情况进行警告*/
#define KERN_NOTICE 5/*正常但又重要的条件,用于提醒*/
#define KERN_INFO 6/*提示信息,如驱动程序启动时,打印硬件信息*/
#define KERN_DEBUG 7/*调试级别的消息*/
2.4 内核Makefile编写
Makefile
obj-m := helloworld.o //默认使用obj-m的形式 #hello-objs := file1.o file2.o file3.o //这个可以分模块的方式 KDIR := /home/doctmp/part4/linux-tq2440 //设置tq2440的内核目录 all: make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm //-C 表明使用的内核目录 M表示需要编译的目录(PWD大写!) modules:make modules (编译内核)后面用交叉工具链 clean: rm -f *.o *.ko *.order *.symvers *.mod.c //设置清除指令
三、内核模块可选信息
3.1 模块申明
1、
MODULE_LICENSE
(”遵守的协议”)
申明该模块遵守的许可证协议,如:“GPL“、”GPL v2“等
2、
MODULE_AUTHOR
(“作者”)
申明模块的作者
3、
MODULE_DESCRIPTION
(“模块的功能描述")
申明模块的功能
4、
MODULE_VERSION
("V1.0")
申明模块的版本
3.2 模块参数
在应用程序中
int main(int argc, char** argv),
argc表示命令行输入的参数个数,argv中保存输入的参数。 同理:
同理:
通过宏
module_param
指定保存模块参数的变量。模块参数
用于在加载模块时传递参数给模块。
module_param(name,type,perm);
name:变量的名称
type:变量类型,bool:布尔型 int:整型 charp:字符串型
perm是访问权限。 S_IRUGO:读权限 S_IWUSR:写权限
例:
nt a = 3;
char *st;
module_param(a,int, S_IRUGO);
module_param(st,charp, S_IRUGO);
3.3 符号输出
内核符号的导出使用宏
EXPORT_SYMBOL
(符号名)
EXPORT_SYMBOL_GPL
(符号名)
说明:
其中EXPORT_SYMBOL_GPL只能用于包含GPL许可证的模块。 再写一个add.c,修改helloworld调用add()函数。
#include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("GPL"); int add(int a, int b) { return a+b; } static int add_init(void) { return 0; } static void add_exit(void) { printk(KERN_WARNING"add_exit"); } EXPORT_SYMBOL(add); module_init(add_init); module_exit(add_exit);
如果不加EXPORT_SYMBOL的话,会出现以下错误:
# insmod add.ko # insmod helloworld.ko helloworld: Unknown symbol add insmod: cannot insert 'helloworld.ko': unknown symbol in module or invalid parameter
尽管加上extern表示外部引用,最后依然不能完成加载,哪怕顺序一致。加上export_symbol后就能让helloworld使用了。
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(64) | 评论(0) | 转发(0) |
0
上一篇:根文件系统制作
下一篇:Linux内核子系统
相关热门文章
SHTML是什么_SSI有什么用...
查看linux中某个端口(port)...
卡尔曼滤波的原理说明...
shell中字符串操作
关于java中的“错误:找不到或...
给主人留下些什么吧!~~
评论热议