RK3568驱动指南|驱动基础进阶篇-进阶5 自定义实现insmod命令实验

发布时间:2024年01月15日

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。

?
【公众号】迅为电子

【粉丝群】824412014(加群获取驱动文档+例程)

【视频观看】嵌入式学习之Linux驱动(驱动基础进阶篇_全新升级)_基于RK3568

【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板


进阶5 自定义实现insmod命令实验

5.1 实验程序的编写

在本章节将会实现第二种方法实现insmod命令。

5.1.1 驱动程序编写

本实验对应的网盘路径为:iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动例程\52_module02\01_module

编写完成的helloworld.c代码如下所示。

#include <linux/module.h>
#include <linux/kernel.h>

static int __init helloworld_init(void) //驱动入口函数
{
    dump_stack();
    return 0;                                                                                                                                                                                                                                             
}

static void __exit helloworld_exit(void) //驱动出口函数
{
    printk(KERN_EMERG "helloworld_exit\r\n");
}

module_init(helloworld_init); //注册入口函数
module_exit(helloworld_exit); //注册出口函数
MODULE_LICENSE("GPL v2"); //同意 GPL 开源协议
MODULE_AUTHOR("topeet"); //作者信息

该驱动程序就是最简单的helloworld驱动程序,只是在第6行添加了dump_stack()函数,用来在内核中输出当前调用堆栈信息,在这里使用该函数的目的是验证在app中的init_module系统调用是否生效。

5.1.2 编写测试 APP

本应用程序对应的网盘路径为:iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动例程\52_module02\02_app。

编写完成的应用程序app.c代码如下所示:

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

#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)

int main(int argc, char **argv)
{
    int fd;                  // 文件描述符
    int ret;                 // 返回值
    struct stat statbuf;     // 存储文件信息的结构体
    size_t image_size;       // 文件大小
    char *image;             // 文件内容缓冲区

    fd = open(argv[1], O_RDONLY | __O_CLOEXEC);  // 以只读方式打开文件
    if (fd < 0)
    {
        printf("open error \n");  // 打开文件失败
        return -1;
    }
    fstat(fd, &statbuf);       // 获取文件信息
    image_size = statbuf.st_size;  // 获取文件大小
    image = malloc(image_size);  // 为文件内容分配内存空间
    read(fd, image, image_size);  // 读取文件内容到缓冲区

    ret = init_module(image, image_size, "");  // 调用系统调用初始化内核模块
    if (ret < 0)
    {
        printf("error \n");  // 内核模块初始化失败
    }
    else
    {
        printf("ok \n");  // 内核模块初始化成功
    }

    free(image);  // 释放内存空间

    return ret;  // 返回结果
}

该应用程序的重点在30行,使用init_module系统调用加载模块到内核。

5.2运行测试

5.2.1 编译驱动程序

在上一小节中的helloworld.c代码同一目录下创建 Makefile 文件,Makefile 文件内容如下所示:

export ARCH=arm64#设置平台架构
export CROSS_COMPILE=aarch64-linux-gnu-#交叉编译器前缀
obj-m += helloworld.o    #此处要和你的驱动源文件同名
KDIR :=/home/topeet/Linux/linux_sdk/kernel    #这里是你的内核目录                                                                                                                            
PWD ?= $(shell pwd)
all:
    make -C $(KDIR) M=$(PWD) modules    #make操作
clean:
    make -C $(KDIR) M=$(PWD) clean    #make clean操作

对于Makefile的内容注释已在上图添加,保存退出之后,来到存放helloworld.c和Makefile文件目录下,如下图(图5-1)所示:

图 5-1

然后使用命令“make”进行驱动的编译,编译完成如下图(图5-2)所示:

图 52

编译完生成platform_led.ko目标文件,如下图(图5-3)所示:

图 53

至此驱动模块就编译成功了。

5.2.2 编译应用程序

下面进行应用程序编译,因为测试APP是要在开发板上运行的,所以需要aarch64-linux-gnu-gcc来编译,输入以下命令,编译完成以后会生成一个app的可执行程序,如下图(图141-4)所示:

aarch64-linux-gnu-gcc myinsmod.c

图 5-4

下面进行驱动程序的测试。

5.2.3运行测试

本次测试要使用上面编译的helloworld.ko驱动文件和a.out可执行文件,所以需要先将两个要用到的文件拷贝到开发板上。

开发板启动之后,使用以下命令加载helloworld.ko驱动,如下图所示:

./a.out helloworld.ko

?

图5-5

dump_stack函数会打印调用的一系列函数,这些函数的具体调用已经在进阶第一章讲解过了,这里的重点为红色框中的倒数第二行,调用了init_module函数加载了helloworld驱动。

然后继续使用以下命令查看驱动的加载情况,打印如下图(141-6)所示:

lsmod

?

图 5-6

可以看到helloworld驱动成功加载上了,最后可以使用以下命令进行驱动的卸载,如下图(图141-7)所示:

rmmod

?

图 5-7

至此,内核是如何运行KO文件的_insmod实验就完成了。

?

文章来源:https://blog.csdn.net/BeiJingXunWei/article/details/135599484
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。