首页 > 解决方案 > 内核模块的加载如何在 linux 中工作?

问题描述

试图了解内核模块的内部结构。

加载内核模块时会发生什么?模块是作为不同的进程运行还是作为内核代码的一部分运行?即为加载的模块分配的文本段和数据段在哪里?

标签: kernelkernel-module

解决方案


模块本身不会运行,它会被加载,并且当您调用模块的打开/读/写函数时代码将运行,这些函数将作为文件呈现给用户模式。

对于 x86-64,内核加载在 0xffff_ffff_8000_0000 以上。因此,内核模块将在附近的某个地方分配内存。

您可以查看 /boot 目录中引导分区上的 System.map 文件,以了解不同的内核功能在哪里。

当您从 C++ 对内核模块的文件调用 open 时,您会调用 libstdc++ 中的瘦包装器,该包装器会在内核中进行系统调用。系统调用将调用模块的 open 函数,然后返回给调用者。因此它将在内核中进行一个小的上下文切换。该代码位于规范虚拟地址空间的最后 2GB 中。

内核模块是可重定位的可执行文件。它们将被重新定位在内核区域(上 2GB)的虚拟地址空间中的某个位置。它们可以降落在物理地址空间的任何地方。

内核模块由 insmod 程序使用 System.map 文件重新定位。insmod 程序将调用模块的 init 函数作为 sudo。加载模块后,除非您从涉及系统调用的用户模式进程调用模块文件的 open 函数,否则不会运行任何内容。该模块只是存在于内存中的某个地方并准备好被调用。您从模块调用的所有函数都使用 System.map 文件与内核动态链接。


推荐阅读