第4章 内核模块实验(iTOP-RK3568开发板驱动开发指南 )

在上一章节我们编写了最简单的helloworld驱动程序。有了驱动程序以后,要如何编译并使用驱动呢。编译驱动有俩种方法,分别是将驱动编译成内核和将驱动编译成内核模块。我们先来学习如何将驱动编译成内核模块、

4.1 设置交叉编译器

1 下载网盘资料下的交叉编译器,网盘路径为:“XXX”,将下载的交叉编译器拷贝到Ubuntu的/usr/local目录下,如下图(图4-1)所示:

img

图 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

img

图 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章 内核模块实验(iTOP-RK3568开发板驱动开发指南 )_第1张图片

图 4-3

4 保存退出,在终端输入“reboot”命令重新启动Ubuntu系统,使交叉编译环境生效。Ubuntu系统重新启动之后,登录到系统后,打开终端,输入命令“aarch64-linux-gnu-gcc -v”,如果终端有如下图(图4-4)所示的打印信息,说明交叉编译环境搭建成功。如果没有出现如下图(图4-4)的打印信息,需要检查上一步骤是否设置正确。

第4章 内核模块实验(iTOP-RK3568开发板驱动开发指南 )_第2张图片

图 4-4

4.2 编写Makefile

编译驱动程序还需要使用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

代码解释如下:

  • 第1行设置ARCH变量为arm64
  • 第2行设置交叉编译器前缀为aarch64-linux-gnu-
  • 第3行obj-m += <文件>:将指定的文件(需要是以.o结尾)设为编译时以模块形式编译
  • 第4行是设备树内核的源码路径,请大家根据实际内核路径进行修改。
  • 第5行是获取当前目录的变量
  • 第7行是编译make操作,会进入内核源码的路径,然后把当前路径下的代码编译成模块。
  • 第9行是清除编译文件

编写完成如下图(图4-6)所示:

img

图 4-6

4.3 编译模块

有了Makefile以后,输入“make”命令就可以编译helloworld驱动模块,如下图(图4-7)所示:

第4章 内核模块实验(iTOP-RK3568开发板驱动开发指南 )_第3张图片

图 4-7

编译完生成helloworld.ko目标文件就是我们需要的内核模块。内核模块是以ko为后缀名,如下图(图4-8)所示:

img

图 4-8

输入“make clean”命令清除编译文件,如下图(图4-9)所示:

第4章 内核模块实验(iTOP-RK3568开发板驱动开发指南 )_第4张图片

图 4-9

4.4 模块加载与卸载

有了内核模块以后,我们要如何使用呢?编译驱动有俩种方式,那Linux驱动的运行方式也肯定有俩种。一种就是将驱动编译进内核,这样Linux系统启动后会自动运行程序。第二种就是将驱动编译成模块,在Linux系统启动以后使用“insmod”命令加载驱动模块。

在上个小节中编译了驱动模块helloworld.ko,在RK3568开发板上通过“insmod helloworld.ko”命令可以加载驱动,在加载驱动模块的时候会执行驱动入口的函数,也就是helloworld程序中的helloworld_init函数,所以可以看到打印出来的字符串信息“helloworld_init”。如下图(图4-10)所示:
img

图 4-10

如果要卸载helloworld内核模块,可以通过“rmmod helloworld”命令来卸载驱动模块,同理在卸载驱动模块的时候会执行驱动出口的函数,所以可以看到驱动出口函数打印出来的字符串信息“helloworld_exit”,如下图(图4-11)所示:

第4章 内核模块实验(iTOP-RK3568开发板驱动开发指南 )_第5张图片

图 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命令来卸载。

4.5查看模块信息

在驱动模块加载之后,使用“modinfo helloworld.ko”命令可以获得模块的信息,包括模块作者,模块说明,模块支持的参数等等。

lsmod 命令可以列出已经载入Linux内核模块,在helloworld驱动加载之后,查看内核中加载的模块,如下(图4-12)所示:

第4章 内核模块实验(iTOP-RK3568开发板驱动开发指南 )_第6张图片

图 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

你可能感兴趣的:(驱动开发)