Linux内核驱动模块学习

.ko文件格式

.ko文件在是elf(Excutable and Link Format)格式,是一种可重定位的目标文件。在编译驱动模块时,我们在makefile中用obj-m=xxx.o来指定生成内核驱动模块文件,即.ko文件。
在这里插入图片描述

模块加载过程

首先insmod会通过文件系统将ko读到用户空间的一块内存中, 然后执行系统调用sys_init_module()解析模组,这时,内核在vmalloc区分配与ko文件大小相同的内存来暂存ko文件, 暂存好之后解析ko文件,将文件中的各个section分配到init 段和core 段,在modules区为init段和core段分配内存, 并把对应的section copy到modules区最终的运行地址,经过relocate函数地址等操作后,就可以执行ko的init操作了, 这样一个ko的加载流程就结束了。 同时,init段会被释放掉,仅留下core段来运行。

内核模块加载过程

输入指令rmmod,最终在系统内核中需要调用sys_delete_module进行实现。具体过程如下:先从用户空间传入需要卸载的模块名称,根据名称找到要卸载的模块指针, 确保我们要卸载的模块没有被其他模块依赖,然后找到模块本身的exit函数实现卸载。

内核导出符号

在Linux内核中,符号是指模块中使用EVPORT_SYMBOL声明的函数和变量。当模块被装入内核后,它所到处的符号都会被记录在内核符号表中,在使用insmod加载模块后,模块就被连接到内核,因此可以访问内核的公用符号。内核导出符号被称为模块层叠技术,当其他模块想要从这个模块使用某些资源时,就可以考虑使用导出符号为其提供服务,如此一来,我们可以将模块分为多个层,通过简化每一层来实现复杂的项目。modprobe是一个处理层叠模块的工具,它的功能相当于多次使用insmod, 除了装入指定模块外还同时装入指定模块所依赖的其他模块。导出符号使用下面的宏

EXPORT_SYMBOL(NAME)
EXPORT_SYMBOL_GPL(NAME)

__init、__initdata等宏定义

__init用来修饰函数,__initdata用于修饰变量。带有__init的修饰符,表示将该函数放到可执行文件的__init节区中,该节区中的内容只能用于模块的初始化阶段,初始化阶段执行完毕之后,这部分的内容就会被释放掉,所以我个人认为这是一种很好的节约系统内存的方式。__exit,表示将该函数放在可执行文件的__exit节区, 当执行完模块卸载阶段之后,就会自动释放该区域的空间。__exit用于修饰函数,__exitdata用于修饰变量。 宏定义module_exit用于告诉内核,当卸载模块时,需要调用哪个函数。
__init、__initdata宏定义(位于内核源码/linux/init.h)

#define __init __section(.init.text) __cold notrace
#define __initdata __section(.init.data)

module_init宏定义

#define module_init(x) __initcall(x);

module_exit宏定义

#define module_exit(x) __exitcall(x);

__exit、__exitdata宏定义

#define __exit __section(.exit.text) __exitused __cold notrace
#define __exitdata __section(.exit.data)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值