Communicating between multiple distinct kernel modules (drivers)

无人久伴 提交于 2019-12-24 02:33:42

问题


In order to achieve better encapsulation and modularity I've decided to split my kernel driver into 2 (can be more) modules where each is responsible for different functionality.

However, there are still some data+logic which I'd like to share between those modules (i.e. one module can manage the communication with user-space, while the other uses it as mediator) and I wonder if there's any easy way to do so.

For example, I'd like to publish some API from one module to another, which is absolutely doable since both modules are running under kernel process and are mapped in separated ranges in the same address space.

The catch is that each kernel module has symbol table of its own, and in order to publish the API, some sort of loader is needed to fix the addressing/pointers/etc.. It's like calling dlopen and dlsym from user-space when dynamically linking with library, but in kernel space and where each library also possess state (the state defined by the current snapshot of all its inner heap/global parameters).

My question is whether this approach is valid and accpeted in the realms of macOS?

EDIT, in the following question, it's explained the linux way of achieving my goal, Perhaps do you know what's the equivalent in macOS/XNU to symbol_get and symbol_put ?


回答1:


It looks like the Linux side has already been answered in comments.

For macOS kexts, the mechanism to use are the OSBundleLibraries and OSBundleCompatibleVersion Info.plist properties. The kext exporting symbols must have the OSBundleCompatibleVersion property set. This must be less than or equal to its CFBundleVersion and allows you to version your API.

The kext which wishes to import the other kext's symbols must list the exporting kext's bundle identifier in the OSBundleLibraries dictionary, with the appropriate version number.

Note that linking against another kext will import all of its public symbols, so I strongly recommend making all symbols default-hidden and providing an explicit exports file. To do this, enable "Symbols hidden by default" in the Xcode target settings, create a new .exp (or .exports) file, and declare it in the "Exported Symbols File" setting. At a minimum, you will need to add _kmod_info to this file. Then add all the symbols you wish to export, one on each line.

C functions and global variables will need to be prefixed with an underscore, C++ functions and static class member variables will need to be mangled in the usual way. You can use * as a (partial) wildcard, which is sometimes handy for C++ classes with a lot of member functions, for example. The xnu source distribution contains plenty of examples of exports files if you need a reference. You can use the nm tool to generate a list of all the symbols in your kext, from which you can then pick & choose; this saves you from manually mangling names.

Kexts can't circularly depend on one another. One will need to be the "library," the other the "user" of that library. If they need to interact, you will need to use callbacks, virtual functions, etc.

The "library" kext must be installed in /Library/Extensions (/System/Library/Extensions on OS X 10.8 or earlier) or the user of the library will not find it, potentially even if the library kext is already loaded. If your "user" kext specifies in its OSBundleRequired property that it may be needed for local or network booting, the libraries it depends on should declare the same or a superset of those conditions, or they may not be appropriately prelinked/kextcached.

Apple does have a small amount of documentation on designing kext libraries too.



来源:https://stackoverflow.com/questions/47755233/communicating-between-multiple-distinct-kernel-modules-drivers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!