当前位置: 首页 > news >正文

insmod后发生了什么

通过 insmod 命令加载 ko 内存模块,加载该内存模块的时候,该内存模块会自动执行module_init() 函数,进行初始化操作。

#ifndef MODULE
// 省略
#define module_init(x)	__initcall(x);
// 省略
#else#define module_init(initfn)	\int init_module(void) __attribute__((alias(#initfn)));
// 省略
#endif

insmod 会通过文件系统将 .ko 模块读到用户空间的一块内存中,然后执行系统调用sys_init_module() 解析模组,代码如下:

1 SYSCALL_DEFINE3(init_module, void __user *, umod,
2 unsigned long, len, const char __user *, uargs)
3 {
4 int err;
5 struct load_info info = { };
6
7 err = may_init_module();
8 if (err)
9 return err;
10
11 pr_debug("init_module: umod=%p, len=%lu, uargs=%p\n",
12 umod, len, uargs);
13
14 err = copy_module_from_user(umod, len, &info);
15 if (err)
16 return err;
17
18 return load_module(&info, uargs, 0);
19 }

• 第 14 行:通过 vmalloc 在 vmalloc 区分配内存空间,将内核模块 copy 到此空间,info->hdr直接指向此空间首地址,也就是 ko 的 elf header 。

• 第 18 行:然后通过 load_module() 进行模块加载的核心处理,在这里完成了模块的搬移,重定向等艰苦的过程。

 下面是 load_module() 的详细过程,代码已经简化,主要包含 setup_load_info()layout_and_allocate()

1 /* 分配并加载模块 */
2 static int load_module(struct load_info *info, const char __user *uargs,
3 					   int flags)
4 {
5 		struct module *mod;
6 		long err = 0;
7 		char *after_dashes;
8 		...
9 		err = setup_load_info(info, flags);
10		 ...
11 		mod = layout_and_allocate(info, flags);
12 		...
13 }

• 第 9 行:setup_load_info() 加载 struct load_infostruct module, rewrite_section_headers,将每个 section 的 sh_addr 修改为当前镜像所在的内存地址,section 名称字符串表地址的获取方式是从 ELF 头中的 e_shstrndx 获取到节区头部字符串表的标号,找到对应 section 在 ELF 文件中的偏移,再加上 ELF 文件起始地址就得到了字符串表在内存中的地址。

• 第 11 行:在 layout_and_allocate() 中,layout_sections() 负责将 section 归类为 core 和 init 这两大类, 为 ko 的第二次搬移做准备。move_module() 把 ko 搬移到最终的运行地址。内核模块加载代码搬运过程到此就结束了。

总结:首先 insmod 会通过文件系统将 .ko 模块读到用户空间的一块内存中,然后执行系统调用sys_init_module() 解析模组, 这时,内核在 vmalloc 区分配与 ko 文件大小相同的内存来暂存ko 文件,暂存好之后解析 ko 文件,将文件中的各个 section 分配到 init 段和 core 段,在 modules 区为 init 段和 core 段分配内存,并把对应的 section 复制到 modules 区最终的运行地址,经过 relocate函数地址等操作后,就可以执行 ko 的 init 操作了,这样一个 ko 的加载流程就结束了。同时,init段会被释放掉,仅留下 core 段来运行。


参考自野火驱动开发教学文档


http://www.mrgr.cn/news/4777.html

相关文章:

  • Linux 软件编程学习第十七天
  • 【图像超分】论文精读:AdaBM: On-the-Fly Adaptive Bit Mapping for Image Super-Resolution
  • Web前端:CSS篇(三)盒子模型,弹性盒子
  • 无人机之喊话器的用途
  • 基于深度学习的位置感知应用
  • esbuild中的Text Loader:简化文本文件处理
  • 【C++初阶】:C++入门篇(一)
  • chmod命令学习1
  • Grafana中的rate与irate以及histogram
  • 基于Ubuntu22.04 安装SSH服务
  • C++中二叉搜索树的底层原理及实现
  • 打卡学习Python爬虫第二天|Web请求过程刨析
  • 【jvm】栈和堆的区别
  • 编译linux内核时,让版本号不跟着git变化
  • c#中Task.Run 和使用 Task 构造函数创建任务的区别
  • PhpStorm环境配置与应用
  • (秋招复习)自动驾驶与机器人中的SLAM技术(三)
  • rust操作rabbitmq
  • Notion使用详解
  • EmguCV学习笔记 VB.Net 2.S 特别示例