vue.js做个人网站,塘厦镇属于东莞哪个区,wordpress4.9标签404,html入门瑞芯微RK3568芯片是一款定位中高端的通用型SOC#xff0c;采用22nm制程工艺#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU#xff0c;可用于轻量级人工… 瑞芯微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(cant 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 ARCHarm64#设置平台架构
export CROSS_COMPILEaarch64-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实验就完成了。