一、模块
模块(module):内核运行时,可以动态添加/删除的代码。
make menuconfig后配置菜单下:
< >:不编译
<*>:静态编译 *.c-->*.o-->zImage
:动态编译 *.c-->*.o-->*.ko
使用模块的好处:内核运行效率高,使用方便,保护知识产权。
模块功能:1、驱动 2、文件系统 3、协议......
|
module
|
app
|
运行空间
|
内核空间(3G~4G)
|
用户空间(0~3G)
|
入口地址
|
加载函数
|
main函数
|
函数调用
|
调内核函数
|
调库函数
|
资源使用
|
自己申请和释放
|
资源自动回收
|
模块三要素:
1、声明许可: MODULE_LICENSE("GPL");
如果不声明许可,内核里很多函数都无法调用
2、加载函数: 为了申请资源 缺省加载函数:int init_module(void);
如果加载函数执行成功,返回0,加载函数执行失败,返回负的错误代码。
3、卸载函数: 为了释放资源 缺省卸载函数:void cleanup_module(void);
使用函数要声明头文件 #include
printk 用法同库函数下的printf 函数;
模块编译和使用条件:1、经过配置编译后的内核源码;2、编译模块所用内核版本和加载模块的内核版本必须一致。
模块编译方法:
1、内部模块:把模块源码拷贝到内核源码下编译
2、外部模块:不需要在内核源码下编译
几个常用命令:
lsmod:查看系统加载模块信息
insmod :加载模块 ,后面要跟上路径和模块名称 如:insmod hello.ko
rmmod :卸载模块,直接跟上模块名字 如:rmmod hello
modprobe :只能加载内部模块,自动处理依赖关系 ,如 modprobe 9p
内部模块一般使用modprobe加载比较方便,外部模块只能用insmod
/lib/modules/<内核版本>/ 下module.dep 存放的所有模块的依赖关系
指定加载模块:
int xx_init(void) 指定加载函数
module_init(xx_init);宏声明函数
指定卸载模块:
void xx_exit(void)
module_exit(xx_exit);
一般加 static 修饰函数
如:static int __init hello_init(void)
__init 静态编译时有意义,所修饰的函数编译的代码存放到内核init.text段,
__exit 静态编译时有意义,不参与到编译中
添加模块的其他信息:
MODULE_AUTHOR("XXX") //作者
MODULE_DESCRIPTION("XXX") //模块描述
二、模块传参:
1、在模块中定义响应的变量
static int len = 1024;
2、把变量声明为模块函数
module_param(len,int,0644)
说明信息:MODULE_PARM_DESC(len,"xxx");
加载:无参数 insmod hello.ko
有参数 insmod hello.ko len = 2048
数组传参 :module_param_array(array,int,&arr_argc,0000)
加载:insmod hello.ko array = 1,2
模块导出符号:
1、EXPORT_SYMBOL("XXX");导出函数
2、EXPORT_SYBOL_GPL("XXX");只有遵循GPL许可的模块才可以使用
多文件模块的编译:
修改Makefile
一个文件: obj-m = hello.o
两个文件,生成两个.ko : obj-m = hello1.o hello2.o
多个文件,生个一个.ko :obj-m = final.o
final-objs = xx.o xx.o
阅读(3543) | 评论(0) | 转发(1) |