目录
Linux 驱动两种运行方式
字符设备驱动框架
1、创建目录和编写文件
2、添加头文件路径
3、Makefile编写和解释
4、编译测试
Linux 驱动两种运行方式
第一种就是将驱动编译进 Linux 内核中,这样当 Linux 内核启动的时候就会自动运行驱动程序;
第二种就是将驱动编译成模块(Linux 下模块扩展名为.ko),在Linux 内核启动以后使用“insmod”命令加载驱动模块。
在调试驱动的时候一般都选择将其编译为模块,这样修改驱动以后只需要编译一下驱动代码即可,不需要编译整个 Linux 代码,而且在调试的时候只需要加载或者卸载驱动模块即可,不需要重启整个系统。
将驱动编译为模块最大的好处就是方便开发,当驱动开发完成,确定没有问题以后就可以将驱动编译进Linux 内核中,当然也可以不编译进 Linux 内核中,具体看自己的需求。
模块有加载和卸载两种操作,在编写驱动的时候需要注册这两种操作函数,模块的加载和卸载注册函数,如下
module_init(xxx_init); module_exit(xxx_exit); |
//注册模块加载函数 //注册模块卸载函数 |
module_init 函数用来向 Linux 内核注册一个模块加载函数,参数 xxx_init 就是需要注册的具体函数,当使用“insmod”命令加载驱动的时候, xxx_init 这个函数就会被调用。 module_exit()函数用来向 Linux 内核注册一个模块卸载函数,参数 xxx_exit 就是需要注册的具体函数,当使用“rmmod”命令卸载具体驱动的时候 xxx_exit 函数就会被调用。
下面开始创建字符设备驱动框架
字符设备驱动框架
1、创建目录和编写文件
在IMX6ULL/Linux_Drivers创建目录1_chrdevbase
在vscode打开目录并并创建chrdevbase.c文件,在chrdevbase.c文件输入下面的代码
#include <linux/module.h>
static int __int chrdevbase_init(void)
{
return 0;
}static void __exit chrdevbase_exit(void)
{
}module_init(chrdevbase_init);
module_exit(chrdevbase_exit);
第 4 行,定义了个名为chrdevbase_init 的驱动入口函数,并且使用了“__init”来修饰
第 11 行,定义了个名为chrdevbase_exit 的驱动出口函数,并且使用了“__exit”来修饰
第 17 行,调用函数 module_init 来声明chrdevbase_init 为驱动入口函数
当加载驱动的时候 chrdevbase_init函数就会被调用
第18行,调用函数module_exit来声明chrdevbase_exit为驱动出口函数
当卸载驱动的时候chrdevbase_exit函数就会被调用
2、添加头文件路径
这里需要给vscode头文件添加路径,因为是编写 Linux 驱动,因此会用到 移植在开发板上面的Linux 源码中的函数。需要在 VSCode 中添加 Linux源码中的头文件路径。打开 VSCode,按下“Crtl+Shift+P”打开 VSCode 的控制台,然后输入“C/C++: Edit configurations(JSON) ”,打开 C/C++编辑配置文件,如下图 所示
打开如下图
需要将 Linux 源码里面的头文件路径添加进来,也就是移植的 Linux 源码中的头文件路径,分别是开发板所使用的 Linux 源码下的 include、arch/arm/include 和 arch/arm/include/generated 这三个目录的路径,注意这里使用绝对路径
添加头文件路径(7-8-9行)以后的 c_cpp_properties.json的文件内容如下所示:
"${workspaceFolder}/**",
"/home/ubantu22/my_linux/linux-imx-rel_imx_4.1.15_2.1.0_ga_my/include",
"/home/ubantu22/my_linux/linux-imx-rel_imx_4.1.15_2.1.0_ga_my/arch/arm/include",
"/home/ubantu22/my_linux/linux-imx-rel_imx_4.1.15_2.1.0_ga_my/arch/arm/include/generated/"
3、Makefile编写和解释
设置好路径之后需要编译测试,也就是将chrdevbase.c 这个文件编译为.ko 模块
创建Makefile,代码如下:
KERNELDIR := /home/ubantu22/my_linux/linux-imx-rel_imx_4.1.15_2.1.0_ga_my
CURRENT_PATH := $(shell pwd)
obj-m := chrdevbase.o
build : kernel_modules
kernel_modules:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modulesclean:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
第 1 行, KERNELDIR 表示开发板所用的 Linux 内核源码目录,使用绝对路径
根据自己的实际情况填写
第 3 行, CURRENT_PATH 表示当前路径,直接通过运行“pwd”命令来获取当前所处路径
第 5 行, obj-m 表示chrdevbase.c 这个文件编译为 chrdevbase.ko 外部可加载模块
chrdevbase.c会先编译成chrdevbase.o文件,再编译成chrdevbase.ko文件
第 7 行,表示要编译构建的是模块
第 9 行,编译构建模块目标
第 10 行,编译构建模块目标的具体编译命令
$(MAKE),表示"make"命令,输入make就执行
-C 表示将当前的工作目录切换到指定目录中,就是 KERNERLDIR 目录,即第1行目录
M 表示模块源码目录,这是CURRENT_PATH,即编译到第3行目录
以后程序会自动到指定的CURRENT_PATH目录中读取模块的源码并将其编译为.ko 文件
“ modules ”与前面的“make”搭配,使用"make"命令即表示编译成模块
第 12 行,清理目标
第 13 行,清理目标的具体命令,清理工作目录和指定的目录,命令为"make clean"
这里的makfile不用指定编译器,因已进入到linux内核中, 移植linux的时候中已指定好编译器
4、编译测试
输入 “ make ”命令开始编译
编译完成之后,查看可以看到有“.ko”文件,并测试清理命令“ make clean”并重新查看一下
可以看到编译出来的也被删除了,测试一下用16核编译,命令“ make -j16”
文章来源:https://www.toymoban.com/news/detail-692622.html
测试到此,说明框架是可以成功编译的文章来源地址https://www.toymoban.com/news/detail-692622.html
到了这里,关于Linux驱动1:入口与出口、头文件路径、makefile编译的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!