RK3568驱动指南|驱动基础进阶篇-进阶4 内核是如何运行ko文件的_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实验就完成了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/705792.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kotlin:组合挂起函数

点击查看&#xff1a;组合挂起函数 中文官网 点击查看&#xff1a;组合挂起函数 英文文档 默认顺序调用 假设我们在不同的地方定义了两个进行某种调用远程服务或者进行计算的挂起函数。我们只假设它们都是有用的&#xff0c;但是实际上它们在这个示例中只是为了该目的而延迟了…

PDF文件转换为图片

现在确实有很多线上的工具可以把pdf文件转为图片&#xff0c;比如smallpdf等等&#xff0c;都很好用。但我们有时会碰到一些敏感数据&#xff0c;或者要批量去转&#xff0c;那么需要自己写脚本来实现&#xff0c;以下脚本可以提供这个功能~ def pdf2img(pdf_dir, result_path…

IDEA环境下项目的模块右下角蓝色小方块缺失的解决方法

一、问题描述 该问题的具体表现就如上图一样&#xff0c;模块——”spring-ioc-xml-01“的应该有一个蓝色的方块。现在蓝色方块缺失了之后&#xff0c;我们需要让maven工程重新识别出这个模块。 二、问题分析 出现这种问题的原因&#xff1a;是当前的maven工程没有能够成功的识…

phtread_cancel函数用于取消线程,但不是实时的

如上图所示&#xff0c;线程函数中没有取消点&#xff08;一般是一些系统调用----man 7 pthreads查看&#xff0c;自定义函数是无效的&#xff09;&#xff0c;则使用pthread_cancle函数不生效。 解决方法&#xff1a;可以添加pthread_testcancle(); 通过pthread_join回收的…

为什么要学习PMP知识,PMP培训哪家好?

IT行业项目管理一枚&#xff0c;曾在做技术的时候对自己的职业发展越来越迷茫&#xff0c;不想干到35岁就参与到失业潮中&#xff0c;一直在想着办法提升自己的能力和竞争力&#xff0c;直到在领导嘴里了解到了PMP认证。也就是它对我的职业发展带来了不少的影响&#xff0c;这其…

Python采集二手车数据信息实现数据可视化展示

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 环境使用: Python 3.10 Pycharm 模块使用: requests >>> pip install requests csv 数据可视化: pandas >>> pip install pandas pyech…

自学Python第十五天-常用的HTML解析工具:bs4、xpath、re

自学Python第十五天-常用的HTML解析工具&#xff1a;bs4、xpath、re BS4安装和引入开始使用find_all() 方法获取标签find() 方法获取标签select() 方法获取标签&#xff0c;css 选择器从标签中获取数据 XPathxpath 基础xpath 语法规则lxml 模块xpath() 方法 REmatch() 方法sear…

git配置SSH

gitLab在Cenos7中安装&#xff0c;在Cenos7系统中执行以下操作 1.生成SSH ssh-keygen -t rsa -C xxxxxx.com 然后一路回车,直到出现以下界面为止(-C 参数是邮箱地址) 2.复制SSH 打开/root/.ssh/id_rsa.pub文件&#xff0c;复制其中的内容 在Linux系统中&#xff0c;/root/.…

初谈软件工程(一)

我就读于兰州交通大学的软件工程专业。虽然在全国众多的985、211高校中&#xff0c;兰州交通大学可能并不显眼&#xff0c;似乎未能跻身这些所谓的“顶尖”行列就意味着不被认可。然而&#xff0c;在甘肃省的教育领域中&#xff0c;它无疑是一座璀璨的明珠&#xff0c;名列前茅…

使用R语言进行主成分和因子分析

一、数据描述 数据来源2013年各地区水泥制造业规模以上企业的各主要经济指标&#xff0c;原始数据来源于2014年&#xff08;《中国水泥统计年鉴》&#xff09;&#xff0c;试对用主成分和因子进行经济效益评价。 地区,企业个数&#xff08;亿元&#xff09;,流动资产合计&…

pytest-配置项目不同环境URL

pytest自动化中&#xff0c;在不同环境进行测试&#xff0c;可以将项目中的url单独抽取出来&#xff0c;通过pytest.ini配置文件实现&#xff08;类似postman中的“Environments”&#xff09; 使用步骤&#xff1a; 1&#xff09;安装pytest-base-url插件 pytest-base-url …

阿里云国际云解析DNS如何开启/关闭流量分析?

流量分析服务会涉及产生日志费用&#xff0c;所以开通内网DNS解析服务后&#xff0c;默认不会主动开启流量分析&#xff0c;需要您手动开启流量分析。对于未开启流量分析的用户&#xff0c;进入界面会提示您展示的都是模拟数据&#xff0c;您可以点击开启流量分析服务&#xff…

【pytorch】常用代码

文章目录 条件与概率torch.tensor()torch.rand()torch.randn()torch.randint()torch.multinominal() 逻辑运算torch.argmax()torch.max()torch.sum()torch.tanh()torch.pow() 功能性操作 torch.nn.functionalF.normalize()F.elu()F.relu()F.softmax() 张量计算torch.zeros()tor…

基于JavaWeb实现的校园新闻发布系统

一、系统架构 前端&#xff1a;jsp | bootstrap | js | css 后端&#xff1a;springboot | jdbc 环境&#xff1a;jdk1.6 | mysql | maven 二、 代码及数据库 三、功能介绍 01. web端-首页 02. web端-新闻列表 03. web端-新闻明细 04. 管理端-登录页…

数据可视化引领智慧工业新时代

在智慧工业的大潮中&#xff0c;数据可视化崭露头角&#xff0c;以其直观、清晰的方式赋能工业生产&#xff0c;为智慧工业的高效运转提供了强有力的支持。下面我就以可视化从业者的角度&#xff0c;简单聊聊这个话题。 数据可视化首先在智慧工业的生产监控中大显身手。通过将…

Vue3前端实现一个本地消息队列(MQ), 让消息延迟消费或者做缓存

MQ功能实现的具体代码(TsMQ.ts)&#xff1a; import { v4 as uuidx } from uuid;import emitter from /utils/mitt// 消息类 class Message {// 过期时间&#xff0c;0表示马上就消费exp: number;// 消费标识&#xff0c;避免重复消费tag : string;// 消息体body : any;constr…

手机打开 第三方 “微信、快手、QQ、电话、信息” 等

前期回顾 Vue3 TS Element-Plus —— 项目系统中封装表格搜索表单 十分钟写五个UI不在是问题_vue3 封装table 配置表格-CSDN博客https://blog.csdn.net/m0_57904695/article/details/135538630?spm1001.2014.3001.5501 目录 &#x1f916; 下载App如下图所示&#xff1a;…

10 款数据恢复软件功能和有效性对比(2024 年更新)

数据丢失可能是一种痛苦的经历&#xff0c;无论是由于意外删除、硬件故障还是软件损坏。值得庆幸的是&#xff0c;数字时代带来了强大的数据恢复解决方案。 随着我们进入 2024 年&#xff0c;市场上充斥着旨在有效检索丢失数据的先进软件。在本文中&#xff0c;我们将探讨 2024…

代码随想录 Leetcode494. 目标和

题目&#xff1a; 代码(首刷看解析 2024年2月26日&#xff09; 思路&#xff1a;根据题意&#xff0c;设两个背包&#xff0c;packageA存放前面是""的数字之和&#xff0c;packageB存放前面是“-”的数字之和 则sum packageA packageB; target packageA - packag…

科普:哪几类人适合做人力RPO蓝海项目?

在当今竞争激烈的市场环境中&#xff0c;人力资源管理对于企业的重要性日益凸显。人办理RPO(招聘流程外包)作为一种新兴的服务模式&#xff0c;帮助企业优化招聘流程&#xff0c;提高招聘效率和质量。那么&#xff0c;哪几类人适合做人力RPO蓝海项目呢?本文将为大家详细总结一…