【问题标题】:Communicating between multiple distinct kernel modules (drivers)在多个不同的内核模块(驱动程序)之间进行通信
【发布时间】:2017-12-11 14:37:03
【问题描述】:

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

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

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

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

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

编辑,在下面的question 中,它解释了实现我目标的 linux 方式,也许你知道 macOS/XNU 中的 symbol_getsymbol_put 是什么?

【问题讨论】:

  • 您的问题没有提到 macOS/xnu,但确实提到了 FreeBSD。它是哪一个?如果是后者,则 kernel-extension 和 xnu 标签不合适。
  • 修复了问题以适合标签。我知道 xnu 驱动程序基础结构与 linux 有很大不同,它基于 C++ 代码,但我正在寻找我们的共享 API/内存来通信驱动程序是否是一种合适的方法。如果您有任何想法/评论关于这种方法,我很乐意听到。谢谢!
  • 目前回答您的问题需要了解 Linux 内核和 Mac OS 内核。例如。我了解 Linux(它的内核模块可以像用户空间库那样进行交互),但不了解 Mac OS。改为询问单个(特定)操作系统。
  • 在 Linux 中,内核模块是对象模块,它们可以(也可以)导出和导入符号。使用modinfonm -g 了解详情。

标签: macos ipc kernel-extension xnu


【解决方案1】:

看来Linux端已经在cmets中回答了。

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

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

请注意,链接到另一个 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 也有少量的documentation on designing kext libraries

【讨论】:

  • 很好的答案,谢谢!我已开始相应地实施,如有任何问题,请告知您
  • 是的,它有效!再次感谢...顺便说一句,我想这是不可能的,但也许你知道我是否可以加载我的客户端 kext,即使库 kext 没有加载(导出符号的“本地”实现)?或者甚至更极端......也许有一种方法可以加载一个 kext 动态决定它的库是否已加载,并相应地在本地和远程实现之间切换。
  • 您可以像在任何其他 Mach-O 二进制文件中一样使用弱符号,但我认为您不能缺少整个 kext 依赖项。我怀疑如果找不到 OSBundleLibraries 之一,即使没有未解析的硬链接,kextd 也不会加载您的 kext。但是,您可以这样做的一种方法是不将其标记为依赖项,而是通过基于 OSObject 的 C++ 类进行所有通信。您可以根据类名(作为字符串)创建此类类的实例,如果该类不存在,它应该只报告错误。因此,如果库 kext 未加载,它应该软失败
  • 这是一个非常有趣的方法,我不知道如果类名在运行时不存在,实现createInstance 的可能性会失败。但是新模块的加载究竟将如何使该类突然存在......也许我会在另一个线程中问它,因为它是一个广泛的话题
  • 嗨,我已经按照您的指示构建了基于通用内核扩展的库 kext,它使用 c++ 类来存储所有逻辑(基于OSObject 的类,以便我可以覆盖它与另一个派生类)。但是,似乎我无法正确释放类对象,也许您可​​以在这里解决我的问题:https://stackoverflow.com/questions/47990273/macos-generic-kernel-extension-with-c-classthanks
猜你喜欢
  • 2014-08-03
  • 2013-01-17
  • 2011-11-24
  • 2012-12-13
  • 1970-01-01
  • 1970-01-01
  • 2016-05-05
  • 2023-03-24
  • 1970-01-01
相关资源
最近更新 更多