基本概念:在内核中添加程序需要完成下面3个步骤;
- 将编写的源代码copy到相应的目录;
- 在kconfig中添加新添加源代码的编译配置选项;(让用户选择是否编译)
- 在makefile中添加新添源代码的编译条目;(往往涉及到当前目录,子目录,父目录多个makefile文件)
linux设备驱动是以内核模块的形式出现的,下面将了解内核模块的概念和结构,然后对各个组成部分详解; 内核模块简介:编译内核时并不包括各种内核模块的功能,当需要某种功能时,以内核模块的形式动态的加载
- 内核编译不包括内核模块,保证了内核的大小;
- 一旦加载某个内核模块,它就和内核中的其他部分完全一样;
- 模块加载函数:_init标识声明
- 模块卸载函数:_exit标识声明
- 模块参数:
可以使用module_param(参数名,参数类型,参数读/写权限) 为模块定义一个参数
例如:module_param(num, int, S_IRUGO);
模块也可以拥有参数数组,形式为“module_param_array(数组名,数组类型,数组长,参数读/写权限)”
使用insmod或者modprobe命令,可以给这些参数赋值
例如输入:insmod book.ko book_name='GoodBook' num=5000
(表示加载book.ko 模块,其中给字符串赋值“GoodBook”,给num赋值5000)
- 导出符号:导出的符号可以被其他模块使用,使用前声明一下即可;感觉有点像函数的输出
- 模块声明和描述:我们可以用 MODULE_AUTHOR、 MODULE_DESCRIPTION、MODULE_ VERSION、MODULE_DEVICE_TABLE、MODULE_ALIAS 分别声明模块的
作者、描述、版本、设备表和别名。
MODULE_DESCRIPTION(description);
MODULE_VERSION(version_string);
MODULE_DEVICE_TABLE(table_info);
MODULE_ALIAS(alternate_name);
- 模块的使用计数:当开始使用某个设备时,内核使用try_module_get()增加管理此设备的owner的计数, 当不再使用此设备时,内核通过module_put()减少管理此设备的模块owner的计数。这样当该模块在使用中的时候,管理此设备的模块不能被卸载,只用未使用该设备时才能被卸载。
这里-C后面跟的是linux内核源代码的目录,M=后面跟的是hello.c和Makefile所在的目录 3、编译过程经历的步骤:
- 生成hello.o文件
- 运行modpost,生成hello.mod.c文件
- 编译生成hello.mod.o文件
- 连接hello.o和hello.mod.o文件,生成hello.ko文件
- 最后离开linux内核所在的目录