3

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

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

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

问题是每个内核模块都有自己的符号表,为了发布 API,需要某种加载器来修复寻址/指针/等。这就像在动态链接时从用户空间调用dlopendlsym库,但在内核空间中,并且每个库还拥有状态(由其所有内部堆/全局参数的当前快照定义的状态)。

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

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

4

1 回答 1

2

看起来 Linux 方面已经在评论中得到了回答。

对于 macOS kexts,使用的机制是OSBundleLibrariesOSBundleCompatibleVersionInfo.plist 属性。kext导出符号必须具有OSBundleCompatibleVersion属性集。这必须小于或等于它CFBundleVersion,并允许您对 API 进行版本控制。

希望导入其他 kext 符号的 kext 必须在字典中列出导出kext 的包标识符,并带有适当的版本号。OSBundleLibraries

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

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

Kexts 不能循环地相互依赖。一个需要成为“库”,另一个是该库的“用户”。如果它们需要交互,则需要使用回调、虚函数等。

“库”kext必须安装在 /Library/Extensions(OS X 10.8 或更早版本上的 /System/Library/Extensions)中,否则即使库 kext 已经加载,库的用户也可能找不到它。如果您的“用户”kext 在其OSBundleRequired属性中指定本地或网络引导可能需要它,则它所依赖的库应声明相同或这些条件的超集,否则它们可能未适当地预链接/kextcached。

Apple 也有少量关于设计 kext 库的文档

于 2017-12-12T13:04:41.510 回答