首页 > 其他分享 >RK3568驱动指南|驱动基础进阶篇-进阶6 内核运行ko文件实验——系统调用

RK3568驱动指南|驱动基础进阶篇-进阶6 内核运行ko文件实验——系统调用

时间:2024-02-18 15:22:50浏览次数:30  
标签:__ 调用 进阶 RK3568 系统 module init 驱动 函数

瑞芯微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主板

进阶6 内核运行ko文件实验——系统调用
在前面的学习中,我们了解到insmod命令的功能。当我们使用insmod命令加载ko文件时,它会调用系统调用init_module或finit_module。那么,什么是系统调用呢?接下来我们来进一步探索系统调用。

6.1 什么是系统调用
系统调用(system call)是操作系统提供给应用程序的编程接口,用于访问操作系统的服务和功能。它是应用程序与操作系统之间的桥梁,允许应用程序请求操作系统执行特定的操作,例如文件操作,进程管理,网络通信等。在计算机系统中,应用程序运行在用户态下,而操作系统运行在内核态下。用户态的应用程序无法直接访问操作系统的内核功能和资源,只能通过系统调用来向操作系统发出请求。当应用程序需要执行操作系统提供的服务或访问底层资源时,它会通过系统调用接口向操作系统发送请求,并传递必要的参数。操作系统接收到请求后,会在内核态下执行相应的操作,并将结果返回给应用程序。

举个例子来说明,假设小A同学去饭店吃饭。饭店提供了菜单,厨师会根据顾客点的菜来准备食物。在这个例子中,顾客相当于上层应用程序,顾客想要吃鱼香肉丝,可以通过服务员(类比系统调用)点这道菜。服务员接收到顾客的点菜请求后,将其传达给厨师(类比操作系统)。厨师根据订单准备食物,最后将食物交给服务员,服务员再将食物送到顾客面前。

这个例子说明了上层应用程序无法直接操作底层硬件,而是通过系统调用接口与操作系统进行交互来实现对硬件的访问。系统调用是与特定的CPU架构相关的,并且与操作系统的内核版本也有关系。

回到init_module和finit_module这俩个系统调用,它们是应用程序调用的系统调用。当应用程序调用这些系统调用时,操作系统内核会执行加载和运行ko文件的操作。这样,应用程序就能通过系统调用向操作系统请求加载内核模块的功能。

6.2 系统调用的流程
以init_module为例,init_module的原型为如下所示:

#include <linux/module.h>

int init_module(void *module_image, unsigned long len, const char *param_values);

参数说明:

module_image:指向内核模块的内存映像的指针。
len:内核模块的大小(以字节为单位)。
param_values:用于传递内核模块参数的字符串。
返回值:成功加载并初始化内核模块时,返回0。加载和初始化内核模块失败时,返回负数值,表示错误代码。

syscall函数是一个系统调用的包装函数,用于在C/C++程序中调用系统调用。每个系统有一个唯一的系统调用号来标识对应的函数。它的原型如下:

long syscall(long number, ...);

参数说明:

number:系统调用的编号。不同的系统调用有不同的编号,可以在系统调用的文档或头文件中找到相应的编号。
...:可变参数,用于传递系统调用的参数。具体的参数个数和类型取决于不同的系统调用。
返回值:系统调用执行成功时,返回系统调用的结果或返回值。系统调用执行失败时,返回负数值,表示错误代码。错误代码的具体含义可以在系统调用的文档或头文件中找到相应的定义。

作用:根据系统调用号,调用相应的系统调用

那__NR_init_module 和哪个函数绑定了呢?打开include/uapi/asm-generic/unistd.h文件,找到以下代码:

/* kernel/module.c */

#define __NR_init_module 105

__SYSCALL(__NR_init_module, sys_init_module)

#define __NR_delete_module 106

__SYSCALL(__NR_delete_module, sys_delete_module)

__SYSCALL将系统调用号与sys_init_module函数绑定。这里有一个规律,在用户空间我们使用xxx函数,对应的系统调用的函数就是sys_xxx;

sys_init_module函数定义在kernel/module.c文件中。sys_init_module函数定义是一个宏定义。如下图所示

 

SYSCALL_DEFINE3(init_module, void __user *, umod,
unsigned long, len, const char __user *, uargs)
{
int err;
struct load_info info = { };

err = may_init_module();
if (err)
return err;

pr_debug("init_module: umod=%p, len=%lu, uargs=%p\n",
umod, len, uargs);

err = copy_module_from_user(umod, len, &info);
if (err)
return err;

return load_module(&info, uargs, 0);
}

在上面的系统调用函数将用户空间的模块数据复制到内核空间,并调用load_module函数加载和初始化该模块。在load_module函数中,完成模块的加载过程,返回do_init_module函数进行模块的初始化。在do_init_module函数中,如果模块的init函数不为空,调用do_one_initcall函数执行模块的初始化函数。在do_one_initcall函数中,执行一个初始化调用函数,这个函数通常在内核初始化过程中使用,用于执行各个模块的初始化函数。

这个宏定义非常复杂,大家只要记住SYSCALL_DEFINE3(init_module, void __user *, umod,

unsigned long, len, const char __user *, uargs)等价于__se_sys_init_module函数即可。这也就解释了为什么当我调用这个系统调用的时候会调用__se_sys_init_module函数。

 

图6-1

标签:__,调用,进阶,RK3568,系统,module,init,驱动,函数
From: https://www.cnblogs.com/topeet/p/18019363

相关文章

  • 7.NET中GRPC进阶,可空类型,返回集合
     1.添加两个类,一个类型可空,一个不可空publicclassPerson1{publicintId{get;set;}publicdoubleMoney{get;set;}publicfloatWeight{get;set;}publicboolGender{get;set;}publiclongPhoneNum{get;set;}publicst......
  • 防干扰LCD显示液晶驱动VK2C23A/B 适用于胎压监测器,胎压仪表,胎压显示,胎压检测器等仪表
    VK2C23A/B概述:      VK2C23A/B是一个点阵式存储映射的LCD驱动器,可支持最大224点(56SEGx4COM)或者最大416点(52SEGx8COM)的LCD屏。单片机可通过I2C接口配置显示参数和读写显示数据,也可通过指令进入省电模式。其高抗干扰,低功耗的特性适用于水电气表以及工控仪表类产品。特点:•......
  • 【Vue前端】vue使用笔记0基础到高手第2篇:Vue进阶知识点介绍(附代码,已分享)
    本系列文章md笔记(已分享)主要讨论vue相关知识。Vue.js是前端三大新框架:Angular.js、React.js、Vue.js之一,Vue.js目前的使用和关注程度在三大框架中稍微胜出,并且它的热度还在递增。Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有非常容易上手的API。Vue.js是一个构建数据驱动......
  • 大数进阶(3)——稳定(单段)
    前言接下来的稳定序数是真正的空白地带,其行为多种多样,层级复杂嵌套,并且还没有被完全解析\(\Sigma_1\)稳定定义定义:若\(L_\alpha\prec_{\Sigma_1}L_\beta\),则称\(\alpha\)是\(\Sigma_1\)稳定(stable)序数,\(\alpha\)稳定到\(\beta\),记为\(\lambda\alpha.\beta\)或者\(\alpha\ri......
  • 大数进阶(2)——反射($\Pi_2$及其上)
    前言\(\Pi_1\)反射看上去行为非常简单,强度也不高,那为什么要用这种奇怪的东西?真正上强度是从\(\Pi_2\)反射开始,随着强度的大幅度提升,序数的行为逐渐复杂,这需要对其行为更深刻的理解,也即对于数学基础的更高要求在进入\(\Pi_2\)反射之前,需要更多的基础来往后推进,否则只会一头雾水......
  • 线段树进阶
    线段树进阶动态开点定义动态存储数据的线段树,可以优化空间复杂度实现为了避免\(N<<1\),不再使用完全二叉树存储,而记录左右儿子\(ls,rs\)此外需要\(tot\)记录已经开了多少点在递归时要记录点的左右区间,确保开点时能知道区间大小voidmodify(int&p,intL,intR,intl,i......
  • 线段树进阶
    线段树进阶线段树分治P5787判断二分图可以用扩展域并查集,采用线段树分治,线段树上的每一个结点作为每一段时间。每个结点上的修改和回溯需要用到可撤销的并查集。时间复杂度\(O(n\logk\logn)\)扫描线扫描线求矩形面积#include<bits/stdc++.h>usingnamespacestd;typ......
  • 大数进阶(1)——反射(Π1)
    一点吐槽序数分析(OrdinalAnalysis)这一脉实际上是从证明论衍生出来的,因此去找文献通常会找到各种证明某一公理系统强度的文献,并没有系统的综述踏入序数之后,几乎没有统一记号,需要在各人的记号中切换,加之数理逻辑本身就需要一堆新记号,可谓是乱七八糟,有一种踏入前沿的美(确实即使从G......
  • 《AI驱动下的开发者新生态》-2024长沙.NET技术社区活动-诚邀大家报名
    回顾2019年初,在.NET中文社区及包括苏州、广州、深圳等地区社区等大力推动、在众多企业的大力支持下,长沙地区的开发者们发起成立了长沙.NET技术社区,并组织了《2019年长沙开发者技术大会》,当时参会人数超过200多人,会上宣讲的约6个话题,也一度成为长沙地区比较热门的技术话题,在社区激......
  • 迈从AX5 PRO MAX拆解以及驱动说明
    迈从黑武士AX5PROMAX拆解图看到拆解可以了解以下:编码器是防尘的、鼠标微动是TTC的光微动,是免焊接的,后续更换方便。鼠标正面涂了三防漆,背面无。按键柱的两个贴片目测至少0.7MM以上 鼠标微动手感:脆闷AX5PROMAX型号: 602535500MA 电池数据:长36MM、宽24.5MM、厚度5.8MM电......