在 OS 中,为啥可加载内核模块 (LKM) 不需要调用消息传递来进行通信?

Posted

技术标签:

【中文标题】在 OS 中,为啥可加载内核模块 (LKM) 不需要调用消息传递来进行通信?【英文标题】:In OS, why loadable kernel modules (LKMs) don't need to invoke message passing in order to communicate?在 OS 中,为什么可加载内核模块 (LKM) 不需要调用消息传递来进行通信? 【发布时间】:2021-10-07 05:37:27 【问题描述】:

我的问题在于一个段落,段落显示如下,我看不懂粗体的句子。如果它不需要调用消息传递,它如何完成进程之间的通信?

模块

也许目前最好的操作系统设计方法包括 使用可加载内核模块(LKM)。这里,内核有一组核心 组件,并且可以在启动时通过模块链接其他服务 或在运行时。这种类型的设计在现代实现中很常见 UNIX,如 Linux、macOS 和 Solaris,以及 Windows。

设计思路是让内核提供核心服务,而 其他服务在内核运行时动态实现。链接 动态服务优于直接向内核添加新功能, 这将需要在每次进行更改时重新编译内核。 因此,例如,我们可以构建 CPU 调度和内存管理 算法直接进入内核,然后添加对不同文件的支持 系统通过可加载的模块。

总体结果类似于分层系统,每个内核部分 已定义、受保护的接口;但它比分层系统更灵活, 因为任何模块都可以调用任何其他模块。该方法也类似于 主模块只有核心功能的微内核方法 以及如何加载和与其他模块通信的知识;但它 更高效,因为模块不需要调用消息传入 为了沟通

Linux 使用可加载内核模块,主要用于支持设备 驱动程序和文件系统。 LKM 可以在系统启动(或引导)或运行时“插入”到内核中,例如当 USB 设备启动时 插入正在运行的机器。如果Linux内核没有必要的驱动,可以动态加载。 LKM 可以从 内核在运行时也是如此。对于 Linux,LKM 允许动态和模块化 内核,同时保持单片系统的性能优势。我们 在最后的几个编程练习中涵盖了在 Linux 中创建 LKM 本章。

【问题讨论】:

所有内核模块都可以看到所有的内核内存。因此它们可以通过修改内核中的全局变量(或全局变量指向的数据结构等)进行通信。 【参考方案1】:

在操作系统中,为什么可加载内核模块 (LKM) 不需要调用消息传递来进行通信?

简单的答案是因为它们被加载到内核空间并动态链接;内核可以使用“大部分正常”的函数调用而不是任何更昂贵的方法(消息传递、远程过程调用……)与它通信。

注意:通常(特别是对于 *nix 系统)驱动程序会提供一组指向内核的函数指针(例如,一个用于open(),一个用于read(),一个用于ioctl(),等等)一种“设备上下文”结构;允许内核通过调用驱动程序的函数。函数指针(例如“result = deviceContext->open( ..);”)。

"该方法也类似于微内核方法,因为主模块只有核心功能和如何加载和与其他模块通信的知识;但效率更高,因为模块不需要调用消息传递为了沟通。”

这一段有可能给你一个错误的印象。仅就可扩展性而言,模块化单片内核类似于微内核(两者都比“字面上的单片(一块,像石头)”内核更具可扩展性)。对于其他方面(例如安全性),模块化单片内核与微内核极为不同。

专门针对 Linux;您可以将其视为近 3000 万行(以每年超过 100 万行的速度增长)的潜在安全漏洞,这些漏洞以最高权限级别运行,可以完全访问每条数据,平均发现大约 150 个关键每年的漏洞(谁知道有多少未发现的严重漏洞)。

微内核的主要目标之一是在“内核核心”和其他一切之间设置隔离屏障;这样您最终可能会得到几千行没有增长的内核(并且安全性有了显着提高)。正是这些隔离屏障需要较低效率的通信(例如消息传递)。

"...但它更高效,因为模块不需要调用消息传递来进行通信。"

这可以更准确地表述为“......但它更有效,因为模块不需要通过隔离屏障。”

请注意,消息传递只是通过隔离屏障的一种方式——有共享内存、信号、管道、套接字、远程过程调用等。没有什么说微内核必须使用消息传递,您可以设计一个根本不使用消息传递的微内核。

【讨论】:

以上是关于在 OS 中,为啥可加载内核模块 (LKM) 不需要调用消息传递来进行通信?的主要内容,如果未能解决你的问题,请参考以下文章

从 LKM 读取 ARM CPU 寄存器

lkm func劫持BUG

从零开始写 OS 内核 - 加载可执行程序

如何创建为Android可加载内核模块

linux内核模块编译makefile

linux内核模块编译makefile -2