【Linux驱动】我的第一个Linux驱动(二) —— 驱动模块的加载与卸载

前面已经写好了字符驱动模板,接下来我们要将其编译成模板,并加载到内核。这里使用的开发板是正点原子 I.MX6ULL MINI版


目录

一、编译驱动模块

二、加载驱动模块

1、创建目录 /lib/modules/4.1.15-g3dc0a4b

2、加载模块

3、查看系统中存在的模块

4、手动创建设备节点文件

5、卸载模块(一开始先跳过)

三、编写应用程序

四、解决 could not open /lib/modules/4.1.15-g3dc0a4b/modules.order


一、编译驱动模块

关于Makefile文件的分析,可以参考该文章中的单文件单模块编译:make modules 模块编译

KERNEL_DIR  		:= /home/ubuntu/tool/linux-imx-kernel
CURRENR_DIR			:= $(shell pwd)

MODULE_NAME			:= chrdevbase                        # 定义模块名
obj-m				:= $(MODULE_NAME).o 

build: kernel_modules
kernel_modules:
	$(MAKE) -C $(KERNEL_DIR) M=$(CURRENR_DIR) modules    # 编译生成模块文件

.PHONY:clean
clean:
	$(MAKE) -C $(KERNEL_DIR) M=$(CURRENR_DIR) clean

如果编译过程中出现了 “ Kernel configuration is invalid ” ,说明你所使用的内核源码没有经过编译,需要先将内核源码进行编译才能使用。

二、加载驱动模块

1、创建目录 /lib/modules/4.1.15-g3dc0a4b

内核默认去 /lib/modules/xxx 下找模块文件,其中 xxx 是内核版本,可以使用uname -r 命令查看。如果目录不存在,需手动创建 

2、加载模块

加载模块有两种方法:insmod 和 modprobe 命令

  • insmod 命令:只会加载指定路径下的某个模块,不会解决依赖
  • modprobe:会帮忙解决依赖,也就是如果加载 a 模块需要 b 模块,那么会先加载 b 模块,再加载 a 模块

insmod 命令

命令格式:insmod  xxx.ko

root@ATK-IMX6U:/lib/modules/4.1.15-g3dc0a4b# insmod chrdevbase.ko
[ 1292.681680] chrdevbase init!

modprobe 命令

使用modprobe命令之前需要先使用 depmod 命令,depmod 命令会扫描一下 /lib/modules/4.1.15-g3dc0a4b 目录下有哪些模块,并将结果写入到 modules.dep 文件中。

执行 depmod 以后会生成如下文件。如果出现了 could not open /lib/modules/xxx/modules.order,请参考本文结尾部分的解决方案。

 接下来就是使用 modprobe 命令将模块加载到内核,加载模块不需要加上后缀!命令格式为:modprobe 模块名

root@ATK-IMX6U:/lib/modules/4.1.15-g3dc0a4b# modprobe chrdevbase
[ 2919.975599] chrdevbase init!

3、查看系统中存在的模块

直接输入 lsmod 命令便可查看当前系统中已经加载到内核的模块

4、手动创建设备节点文件

将模块加载到内核以后,并不会在 /dev 目录下生成对应的驱动文件,这里我们先使用一种临时方式来手动创建设备节点文件,后续等了解了设备树再改用其他方法

# mknod /dev/模块名 c 主设备号 次设备号
mknod /dev/chrdevbase c 200 0
  • mknod:创建节点命令
  • c:表示创建的设备节点是字符设备
  • 200:表示主设备号(需要和模块中设置的保持一致)
  • 0:表示次设备号

5、卸载模块(一开始先跳过)

因为下面我们要配合应用程序进行测试,这里先不卸载模块,等测试完毕我们再卸载模块,卸载模块也很简单,命令格式为:rmmod  模块名

root@ATK-IMX6U:/lib/modules/4.1.15-g3dc0a4b# rmmod chrdevbase
[ 2837.265342] chrdevbase exit!

三、编写应用程序

下面我们需要编写一个简单的应用程序来测试驱动是否能正常工作

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void printHelp()
{
    printf("usage: ./chrdevbaseApp <driver_path>\n");
}

int main(int argc, char* argv[])
{
    if (argc == 1)
    {
        printHelp();
        return -1;
    }
    
    char* filename = argv[1];       // 位置0 保存的是 ./chrdevbaseApp 

    int fd = open(filename, O_RDWR);
    if (fd < 0)
    {
        perror("open file failed");
        return -2;
    }

    const char* txbuf = "hello, world";
    write(fd, txbuf, strlen(txbuf));

    char rxbuf[20] = {0}; 
    read(fd, rxbuf, 20);
    printf("%s\n", rxbuf);

    close(fd);
    
    return 0;
}

将该测试文件编译生成可执行文件  chrdevbaseApp,拷贝到 /lib/moduls/xxx 目录下,运行该文件,如果出现了下面四句话,说明驱动工作正常。

四、解决 could not open /lib/modules/4.1.15-g3dc0a4b/modules.order

根据提示,我们知道是因为modules.order 和 modules.builtin文件缺失。

正点原子的内核源码编译成功后,会在顶层目录下生成 modules.order 和 modules.builtin,我们只需把这两个文件拷贝到开发板的 /lib/modules/xxxx 目录下

参考文章:

Linux驱动编译报错ERROR: Kernel configuration is invalid怎么办_毛炳浩的博客-CSDN博客

imx6ull驱动开发经验_rmmod: error: ../libkmod/libkmod.c:514 lookup_buil_fhqlongteng的博客-CSDN博客

猜你喜欢

转载自blog.csdn.net/challenglistic/article/details/131802308
今日推荐