在多个不同的内核模块(驱动程序)之间进行通信

Communicating between multiple distinct kernel modules (drivers)

为了实现更好的封装和模块化,我决定将我的内核驱动程序拆分为 2 个(可以更多)模块,每个模块负责不同的功能。

但是,我仍然想在这些模块之间共享一些数据+逻辑(即一个模块可以管理与用户-space的通信,而另一个将其用作中介)和我想知道是否有任何简单的方法可以做到这一点。

例如,我想将一些 API 从一个模块发布到另一个模块,这是绝对可行的,因为两个模块都 运行 在内核进程下,并且映射在同一个地址 space。

问题是每个内核模块都有自己的符号 table,为了发布 API,需要某种加载程序来修复 addressing/pointers/etc。 . 这就像在与库动态链接时从 user-space 调用 dlopendlsym,但在内核 space 中每个库也拥有状态(由所有内部 heap/global 参数的当前快照)。

我的问题是这种方法在 macOS 领域是否有效并被接受?

编辑,在下面的 question 中,它解释了实现我的目标的 linux 方法,也许你知道 macOS/XNU 与 symbol_get 中的等价物和symbol_put

好像Linux那边已经在评论里回答了

对于 macOS kexts,使用的机制是 OSBundleLibraries and OSBundleCompatibleVersion Info.plist properties. kext exporting 符号必须设置 OSBundleCompatibleVersion 属性。这必须小于或等于它的 CFBundleVersion 并且允许您对 API.

进行版本控制

希望导入其他kext符号的kext必须在OSBundleLibraries字典中列出exportingkext的包标识符, 以及相应的版本号。

请注意,链接到另一个 kext 将导入其 public 符号的 all,因此我强烈建议将所有符号设为默认隐藏并提供显式导出文件。为此,在 Xcode 目标设置中启用 "Symbols hidden by default",创建一个新的 .exp(或 .exports)文件,并在 "Exported Symbols File" 设置中声明它。您至少需要向该文件中添加 _kmod_info。然后添加所有要导出的符号,每行一个。

C 函数和全局变量需要使用下划线作为前缀,C++ 函数和静态 class 成员变量需要以通常的方式进行修饰。您可以使用 * 作为(部分)通配符,例如,对于具有大量成员函数的 C++ classes 来说,这有时很方便。如果您需要参考,xnu 源代码分发包含大量导出文件示例。您可以使用 nm 工具生成您的 kext 中所有符号的列表,然后您可以从中挑选;这使您免于手动修改名称。

Kext 之间不能循环依赖。一个需要是该库的 "library,",另一个是 "user"。如果他们需要交互,你将需要使用回调、虚函数等。

"library" kext 必须 安装在 /Library/Extensions (/System/Library/Extensions on OS X 10.8 或更早版本)否则库的用户将找不到它,可能即使库 kext 已经加载。 如果您的 "user" kext 在其 OSBundleRequired 属性 本地或网络启动可能需要它,它所依赖的库应该声明相同的条件或这些条件的超集,否则它们可能不合适 prelinked/kextcached.

Apple 也有少量 documentation on designing kext libraries