在上一章节我们编写了最简单的helloworld驱动程序。有了驱动程序以后,要如何编译并使用驱动呢。编译驱动有俩种方法,分别是将驱动编译成内核和将驱动编译成内核模块。我们先来学习如何将驱动编译成内核模块、
1 下载网盘资料下的交叉编译器,网盘路径为:“XXX”,将下载的交叉编译器拷贝到Ubuntu的/usr/local目录下,如下图(图4-1)所示:
图 4-1
2 输入以下命令,解压交叉编译编译器压缩包,解压完毕会生成“gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu”文件夹,这是实验需要的交叉编译工具,如下图(图4-2)所示:
tar -vxf gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu.tar.gz
图 4-2
3 在终端输入“sudo vi /etc/profile”命令,在文件最后输入以下命令修改环境变量。
export PATH=$PATH:/usr/local/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin
图 4-3
4 保存退出,在终端输入“reboot”命令重新启动Ubuntu系统,使交叉编译环境生效。Ubuntu系统重新启动之后,登录到系统后,打开终端,输入命令“aarch64-linux-gnu-gcc -v”,如果终端有如下图(图4-4)所示的打印信息,说明交叉编译环境搭建成功。如果没有出现如下图(图4-4)的打印信息,需要检查上一步骤是否设置正确。
图 4-4
编译驱动程序还需要使用Makefile文件。我们为helloworld.c编写一个简单的Makefile,Makefile文件和源文件helloworld.c位于同一级目录,代码如下(图4-5)所示:
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
obj-m += helloworld.o #helloworld.c对应.o文件的名称。名称要保持一致。
KDIR :=/home/topeet/Linux/linux_sdk/kernel #内核源码所在虚拟机ubuntu的实际路径
PWD ?= $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules #make操作
clean:
make -C $(KDIR) M=$(PWD) clean #make clean操作
图 4-5
代码解释如下:
编写完成如下图(图4-6)所示:
图 4-6
4.3 编译模块
有了Makefile以后,输入“make”命令就可以编译helloworld驱动模块,如下图(图4-7)所示:
图 4-7
编译完生成helloworld.ko目标文件就是我们需要的内核模块。内核模块是以ko为后缀名,如下图(图4-8)所示:
图 4-8
输入“make clean”命令清除编译文件,如下图(图4-9)所示:
图 4-9
有了内核模块以后,我们要如何使用呢?编译驱动有俩种方式,那Linux驱动的运行方式也肯定有俩种。一种就是将驱动编译进内核,这样Linux系统启动后会自动运行程序。第二种就是将驱动编译成模块,在Linux系统启动以后使用“insmod”命令加载驱动模块。
在上个小节中编译了驱动模块helloworld.ko,在RK3568开发板上通过“insmod helloworld.ko”命令可以加载驱动,在加载驱动模块的时候会执行驱动入口的函数,也就是helloworld程序中的helloworld_init函数,所以可以看到打印出来的字符串信息“helloworld_init”。如下图(图4-10)所示:
图 4-10
如果要卸载helloworld内核模块,可以通过“rmmod helloworld”命令来卸载驱动模块,同理在卸载驱动模块的时候会执行驱动出口的函数,所以可以看到驱动出口函数打印出来的字符串信息“helloworld_exit”,如下图(图4-11)所示:
图 4-11
加载驱动模块也可以使用modprobe命令,它比insmod命令更强大,modprobe命令在加载驱动模块的时候,会同时加载该模块依赖的其他模块。比如helloworld.ko依赖before.ko,使用insmod加载的时候,就必须先加载before.ko,然后在加载helloworld.ko才可以加载成功从。但是使用modprobe加载的时候,他会自动分析模块的依赖关系,然后将所有的依赖的模块都加载到内核当中。比较“聪明”。
同样,在卸载驱动模块的时候,如果模块存在依赖关系,如果使用insmod命令,需要手动卸载依赖的内核模块,但是使用modprobe命令可以自动卸载驱动模块所依赖的其他模块。
所以,如果驱动模块是以“modprobe helloworld.ko”命令加载的,卸载的时候使用“modprobe -r helloworld.ko”命令卸载。
但是使用modprobe卸载存在一个问题,如果所依赖的模块被其他模块所使用,比如刚才例子中的before.ko还被其他的模块使用,这时候就不能使用modprobe卸载。所以还是推荐使用rmmod命令来卸载。
在驱动模块加载之后,使用“modinfo helloworld.ko”命令可以获得模块的信息,包括模块作者,模块说明,模块支持的参数等等。
lsmod 命令可以列出已经载入Linux内核模块,在helloworld驱动加载之后,查看内核中加载的模块,如下(图4-12)所示:
图 4-12
【最新驱动资料(文档+例程)】
链接 https://pan.baidu.com/s/1M4smUG2vw_hnn0Hye-tkog
提取码:hbh6
【B 站配套视频】
https://b23.tv/XqYa6Hm
【RK3568 购买链接】
https://item.taobao.com/item.htm?spm=a1z10.5-c-s.w4002-2245
e-tkog
提取码:hbh6
【B 站配套视频】
https://b23.tv/XqYa6Hm
【RK3568 购买链接】
https://item.taobao.com/item.htm?spm=a1z10.5-c-s.w4002-2245
2452613.11.2fec74a6elWNeA&id=669939423234