内核模块--随记

简介

内核模块,可以根据需要去加载进内核或者从内核中卸载的代码块,这操作期间可以不用重启系统。这样使得内核镜像可以按要求裁剪,不用全部功能都去加载进去导致镜像超级大 累赘,而且没有内核模块的方便加载卸载功能,每次添加内核功能,就需要重新编译烧写镜像

module加载卸载

内核模块查看:lsmod,通过读/sys/module目录下的文件获取已经加载进内核的所有模块信息,

模块加载:modprobe 模块名

内核需要加载一个模块时,内核模块daemon程序kmod会执行modprobe将相应模块加载进内核
模块名:cat /etc/modeprobe.d/aliases
知道模块名之后,modprobe会去读/lib/modules/ v e r s i o n / m o d u l e s . d e p , v e r s i o n 是 内 核 版 本 号 , 可 以 使 用 u n a m e − r 得 到 , m o d u l e s . d e p 是 d e m o d − a 命 令 生 成 , 是 将 / l i b / m o d u l e s / version/modules.dep,version是内核版本号,可以使用uname -r得到,modules.dep是demod -a命令生成,是将/lib/modules/ version/modules.depversion使unamermodules.depdemoda/lib/modules/version下所有模块的依赖关系生成到modules.dep中。
然后,modprobe会根据modules.dep中的依赖关系,调用insmod将需要的模块按依赖关系加载

总结:
加载一个module ko的步骤:
1、将ko文件拷贝到/lib/modules/$version目录下
2、调用命令demod -a生成modules.dep
3、调用modprobe 模块名

也可以直接使用insmod +ko文件,但是需要自己处理模块的依赖关系

模块卸载:modpeobe -r 模块名 或者 rmmod 模块名

卸载删除模块时,modprobe和rmmod会去dao/lib/modules/$version下找相应的依赖关系和其他信息,若没有这个目录,卸载删除模块报错

module编写框架

这里先了解一下内核模块和一般应用程序的区别:
1、一般的应用程序,从头到尾执行单个任务,然后到main就立即结束了;设备驱动是预先注册自己以便来服务将来的某个请求,然后它的初始化函数就结束了,就是模块初始化函数的任务就是为以后调用模块函数做准备
2、一般的应用程序在退出时,可以不用管资源的释放或者其他的清除工作;模块的退出函数必须撤销初始化函数做的一切,否则在系统引导之前某些东西就会残留在系统中
3、一般的应用程序可使用从外部引用的函数库,可以调用它自己未定义的函数,因为连接过程中就从那些库中解析到;模块驱动仅仅被链接到内核,它能够调用的函数仅仅是由内核导出的那些函数,不存在任何可连接的函数库
4、一般的应用程序在开发过程中的段错误是无害的,还可以跟踪到源码问题位置;内核错误即使不影响整个系统,也至少会杀死当前的进程,

模块的入口和退出

模块初始化函数init_module();模块退出清理函数cleanup_module()

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

#ifdef MODULE
MODULE_LICENSE("GPL");

int init_module(void)
{
	printk (KERNEL_INFO, "hello!\n");
}

void cleanup_module(void)
{
	printk (KERNEL_INFO, "bye\n");
}
#endif

一般的,init_module或者注册一个handle到内核,或者用自己代码取代内核功能函数;cleanup_module做模块清理工作,释放模块申请的资源。
从内核2.3.13版本开始,可以不用一定使用这两个函数,而可以使用自己定义的函数作为模块的初始化和退出函数,但是要符合init_module和cleanup_module的原型,并且在代码中要加入下面语句:
module_init(hello_init);
module_exit(hello_exit);

模块的编译

编写makefile

obj-m += hello.o
all:
    make -C /lib/modules/$(shell uname -r)/build M = $(PWD) modules
clean:
    make -C /lib/modules/$(shell uname -r)/build M = $(PWD) clean

详细内核编译问题可以查看内核提供的kbuild机制文档:
linux/Documentation/kbuild/modules.rst

2.1 Command Syntax
==================

	The command to build an external module is::

		$ make -C <path_to_kernel_src> M=$PWD

	The kbuild system knows that an external module is being built
	due to the "M=<dir>" option given in the command.

	To build against the running kernel use::

		$ make -C /lib/modules/`uname -r`/build M=$PWD

	Then to install the module(s) just built, add the target
	"modules_install" to the command::

		$ make -C /lib/modules/`uname -r`/build M=$PWD modules_install

License

内核是开源的,要在kernel中写代码,要遵循它的license,linux内核提供一个声明

MODULE_LICENDE ("GPL");

这个声明表示我们的代码遵循GPL(GNU General Public License)协议,其他的一些协议在<linux/module.h>中

模块参数

可以通过命令行来给模块传递初始值的全局变量
1、module_param(name, type, perm)
name:接收参数值的全局变量名
type:变量的类型
perm:参数的权限,和文件权限一般

int gVariable = 1;
module_param (gVariable, int, 0660);

insmod module.ko gVariable = 100

2、module_param_array (name, type, nump, perm)
数组类型的模块全局变量
nump:一个指针,指向的变量存放用户实际传递数组元素的个数,可以设为NULL

3、module_param_string(name, string, len, perm)
string:字符数组名

要描述一个模块参数,可以使用宏(linux/module.h):
MODULE_PARM_DESC (name, desc)

int gVariable = 1;
module_param (gVariable, int, 0660);
MODULE_PARM_DESC (gVariable, "global variable");

insmod module.ko gVariable = 100
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值