瑞芯微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主板
进阶8 内核运行ko文件总结
8.1 内核运行ko流程分析
当我们使用系统调用时,内核会执行SYSCALL_DEFINE3宏定义的函数,如
SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)或SYSCALL_DEFINE3(init_module, void __user *, umod, unsigned long, len, const char __user *, uargs)。这些函数最终都会调用load_module函数,而在load_module函数中,会通过do_one_initcall(mod->init)来执行驱动程序的入口函数。
do_one_initcall函数的作用是执行一个初始化调用函数,并检查执行过程中是否存在抢占不平衡或中断被禁用的情况。如果存在错误信息,会打印警告信息。最后,返回初始化调用函数的返回值。这个函数通常在内核初始化过程中使用,用于执行各个模块的初始化函数。
为什么mod->init就是驱动的入口函数呢?
打开include/linux/module.h文件,找到以下代码,如下图所示:
上述代码是用于定义模块的初始化函数和清理函数的宏定义。通过使用module_init宏和module_exit宏,开发人员可以指定模块的入口函数和清理函数。这些宏定义了一些内联函数和与之关联的特殊命名的函数,以及一些属性和别名,用于在编译时进行检查并将用户定义的函数与特定的模块函数关联起来。
在上图的代码中,int init_module(void) __copy(initfn) __attribute__((alias(#initfn)));:定义一个名为init_module的函数,用于作为模块的入口函数。__copy(initfn)表示复制用户定义的初始化函数,__attribute__((alias(#initfn)))表示将init_module函数与用户定义的初始化函数initfn关联起来。将init_module作为函数initfn的别名。init_module是驱动加载函数的统一别名,当我们编译ko文件的时候,会生成一个.mod.c 的文件。
8.2 内核加载ko文件总结
本篇内容讲解的知识点比较零散,为了更好的总结学习,我们画了以下流程图。
总结一下,要加载内核模块,通常需要使用insmod命令或类似工具触发系统调用,然后在内核中执行相应的系统调用函数(如sys_finit_module或sys_init_module)来加载模块。在加载过程中,会调用load_module函数,进而执行模块的初始化函数。这些过程构成了加载内核模块的流程。