首页 > 其他分享 >RK3568驱动指南|驱动基础进阶篇-进阶4 内核是如何运行ko文件的_insmod

RK3568驱动指南|驱动基础进阶篇-进阶4 内核是如何运行ko文件的_insmod

时间:2024-02-27 15:00:26浏览次数:24  
标签:进阶 RK3568 image finit helloworld module 驱动 insmod 加载

 

 

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

 

 

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

 

 

 

进阶4 内核是如何运行ko文件的_insmod

我们加载驱动一直以来使用的都是insmod命令,那这个insmod命令是哪里来的呢,我们能不能自己实现一个insmod命令呢,带着疑问,让我们进入本节课程的学习吧。

 

4.1 insmod源码分析

在开发板的各种系统中,insmod命令都默认存在了,而命令在本质上也是一个可执行程序,也有着对应的源码,不管是何种系统,insmod命令的源码是相同的(可能会因为版本不同,存在细微的差别),在“iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动例程\51_module\01_busybox源码”目录下提供了busybox源码,

 

 

 

 

然后将busybox源码拷贝到虚拟机Ubuntu上并解压,

 

其中insmod的源码为busybox-1.34.1/modutils/insmod.c,该源码的主要内容如下所示:

 

int insmod_main(int argc UNUSED_PARAM, char **argv)

{

    char *filename;

    int rc;

 

    // 如果是2.4风格的insmod,解析命令行选项

    IF_FEATURE_2_4_MODULES(

        getopt32(argv, INSMOD_OPTS INSMOD_ARGS);

        argv += optind - 1;

    );

 

    // 获取模块文件名

    filename = *++argv;

    if (!filename)

        bb_show_usage();

 

    // 调用bb_init_module函数加载模块

    rc = bb_init_module(filename, parse_cmdline_module_options(argv, /*quote_spaces:*/ 0));

 

    // 如果加载失败,显示错误信息

    if (rc)

        bb_error_msg("can't insert '%s': %s", filename, moderror(rc));

 

    return rc;

}

 

其中最重要的是第18行的bb_init_module函数,正是通过该函数加载的内核模块。该函数定义在busybox-1.34.1/modutils/modutils.c文件中,具体内容如下所示:

 

int FAST_FUNC bb_init_module(const char *filename, const char *options)

{

    size_t image_size;

    char *image;

    int rc;

    bool mmaped;

 

    if (!options)

        options = "";

 

    // TODO: 审查 bb_init_module_24 以符合错误代码约定

#if ENABLE_FEATURE_2_4_MODULES

    if (get_linux_version_code() < KERNEL_VERSION(2,6,0))

        return bb_init_module_24(filename, options);

#endif

 

    // 首先尝试使用finit_module函数加载模块

    // 如果finit_module函数可用,则尝试使用它加载模块

#ifdef __NR_finit_module

    {

        // 打开模块文件

        int fd = open(filename, O_RDONLY | O_CLOEXEC);

        if (fd >= 0) {

            // 调用finit_module函数加载模块,返回值为0表示加载成功

            rc = finit_module(fd, options, 0) != 0;

            close(fd);

            if (rc == 0)

                return rc;

        }

    }

#endif

 

    // 如果finit_module函数不可用,或者调用finit_module失败,则使用其他方式加载模块

 

    // 初始化image_size为INT_MAX-4095,作为映射模块的内存大小

    image_size = INT_MAX - 4095;

    mmaped = 0;

    // 尝试将模块文件映射到内存中

    image = try_to_mmap_module(filename, &image_size);

    if (image) {

        mmaped = 1;

    } else {

        errno = ENOMEM;

        image = xmalloc_open_zipped_read_close(filename, &image_size);

        if (!image)

            return -errno;

    }

 

    errno = 0;

    // 调用init_module函数加载模块,将模块的映像和大小以及选项传递给它

    init_module(image, image_size, options);

    rc = errno;

    if (mmaped)

        munmap(image, image_size);

    else

        free(image);

    return rc;

}

 

在该函数中有着两种模块加载方式,19-31行为第一种使用finit_module系统调用的加载方式,33-57行为第二种使用init_module系统调用的加载方式,默认情况会先使用第一种方式进行模块的加载,如果加载失败了才会使用第二种方式进行加载。两种加载方式的最终实现效果是相同的,而为了加深大家对insmod的理解,我们将根据该函数的内容编写C程序,分别使用第一种方法和第二种方法来加载相应的ko文件。

 

4.2 实验程序的编写

由于章节篇幅的原因,本章节只会实现第一种方法,在下个章节将会实现第二种方法。

 

4.2.1 驱动程序编写

本实验对应的网盘路径为:iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动例程\51_module\02_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中的finit_module系统调用是否生效。

 

4.2.2 编写测试 APP

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

 

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

 

#include <stdio.h>

#include <sys/syscall.h>

#include <fcntl.h>

#include <unistd.h>

 

#define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags)

 

int main(int argc, char **argv)

{

    int fd;     // 文件描述符

    int ret;    // 返回值

 

    fd = open(argv[1], O_RDONLY | O_CLOEXEC);    // 打开文件,以只读方式打开并设置O_CLOEXEC标志

    if (fd < 0) {    // 打开文件失败

        printf("open error\n");

        return -1;

    }

 

    ret = finit_module(fd, "", 0);    // 调用finit_module系统调用加载模块

 

    return ret;    // 返回加载结果

}

 

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

 

4.3 运行测试

4.3.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文件目录下,

 

然后使用命令“make”进行驱动的编译,

 

编译完生成platform_led.ko目标文件,

 

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

 

4.3.2 编译应用程序

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

 

 

 

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

 

4.3.2 运行测试

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

 

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

 

./app helloworld.ko

 

 

 

 

图 4-7

 

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

 

然后继续使用以下命令查看驱动的加载情况,

可以看到helloworld驱动成功加载上了,最后可以使用以下命令进行驱动的卸载,

 

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

标签:进阶,RK3568,image,finit,helloworld,module,驱动,insmod,加载
From: https://www.cnblogs.com/topeet/p/18036897

相关文章

  • 【进阶篇】使用 Redis 实现分布式缓存的全过程思考(一)
    目录前言一、关于缓存二、基本数据结构三、缓存注解3.1自定义注解3.2定义切点(拦截器)3.3AOP实现3.4使用示例四、数据一致性4.1缓存更新策略4.2缓存读写过程五、高可用5.1缓存穿透5.2缓存击穿5.3缓存雪崩5.4Redis集群六、文章小结前言写在前面,让我们从3个问题开始今天的文章:......
  • 三屏异显案例分享,基于全国产RK3568J工业平台!
    在工业领域中,能否更灵活、更高效地在主屏幕进行主要任务,并在其他副屏幕上进行其他次要任务(例如查看参考资料、监控其他应用程序),一直都是许多工业领域客户面临的刚需,而“多屏异显”功能便为此而生。在过去,由于性能、成本、技术等诸多问题,许多工业处理器并不支持多屏异显。但随着工......
  • 无法在驱动器0的分区1上安装Windows
    在通过U盘或光盘安装Win10系统时,不少用户遇到无法安装的问题,提示“无法在驱动器0的分区1上安装Windows”,格式化分区1也不能解决,进而提示Windows无法安装到这个磁盘,选中的磁盘采用GPT/MBR分区形式,这是怎么回事呢?下面跟大家分析出现这个问题的原因以及解决方法。一、原因分析Win......
  • 适用于智能电表、胎压监测、汽机车仪表、计量插座的高抗干扰液晶驱动芯片VK2C23A/B 永
    I²C 接口LCD 控制及驱动IC型号:VK2C23A:RAM 映射 56*4,52*8封装(LQFP-64) LCD液晶显示驱动VK2C23B:RAM 映射 36*8 封装(LQFP-48) LCD液晶显示驱动裸片:DICE(邦定COB)/COG(绑定玻璃用)产品年份:新年份原厂直销,工程服务,技术支持,价格最具优势! VK2C23A/B概述:   ......
  • Unity xLua开发环境搭建与基础进阶
    Unity是一款非常流行的游戏开发引擎,而xLua是一个为Unity开发者提供的Lua框架,可以让开发者使用Lua语言来进行游戏开发。在本文中,我们将介绍如何搭建UnityxLua开发环境,并进行基础进阶的学习。 对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白,也有一些正......
  • ELKF日志系统搭建(二)进阶——使用 Kafka 作为日志消息缓存
    说明:在一些比较大的业务使用场景中,因为应用繁多,需要收集的日志也很多,通过filebeat或者logstash收集上来的日志如果全都直接发送给ES,那么就会对ES集群产生一定的压力,为了避免出现日志接收不过来的问题,于是引入了消息队列作为缓存,比如常见的使用Redis或Kafka作为消息缓存......
  • 《业务建模驱动的企业架构转型白皮书》
    ​当前,我国金融等国民经济重点行业和企业的数字化转型,仍存在战略落地难、业务技术协同难以及投入产出匹配难等问题,亟需通过实施企业架构,从顶层设计出发,制定符合自身需要的转型战略;从全局视角出发,将战略拆解细化为具体可行的措施;从业技融合出发,把握全局需求,优化业务与IT的协同机制......
  • ShowMeBug X MOMA 猛玛 | 提质增效两不误,以技术驱动高效招聘
    ShowMeBug与深圳市昊一源科技有限公司(以下简称昊一源)成功完成签约,并针对其技术人才需求提供全面的解决方案,助力昊一源汇聚优秀技术人才,构建高效招聘流程体系,为昊一源招聘效能的提升和优化奠定坚实基础。依托于ShowMeBug岗位题库和智能组卷功能,昊一源的HR只需要输入岗位名称与岗......
  • Ubuntu22.04下载显卡驱动和CUDA+cuDNN
    注:笔记本电脑-显卡RTX4060-CUDA11.8-cuDNN8.9.7 1:显卡驱动已经安装驱动的,以此卸载已下载驱动sudoapt-getremove--purgenvidia-* 新机器直接进行以下#查看驱动列表sudoaptinstallaptitudesudoaptitudesearchnvidia-driver-*显卡驱动一般选择最新......
  • 动手实践丨轻量级目标检测与分割算法开发和部署(RK3568)
    本文分享自华为云社区《自动驾驶(AIOT)-轻量级目标检测与分割算法开发和部署(RK3568)【玩转华为云】》,作者:HouYanSong。本文将在ModelArts平台上开发轻量级目标检测与分割算法,并使用ModelBox框架在RK3568开发板上实现模型推理和部署。数据准备我们收集了一份200张由Labelme......