linux-kernel – 可以延迟导出符号的加载吗?

前端之家收集整理的这篇文章主要介绍了linux-kernel – 可以延迟导出符号的加载吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用一些 Linux内核模块,并且有一个与循环加载问题相关的问题.

模块A首先加载并导出许多符号,供模块B或C使用.然后,模块B或C随后被加载并且符号存在供其使用.

但是,我现在发现模块A需要来自模块B或C的符号,但仅在运行时期间,而不需要初始化模块.所以当A加载时,它发现该符号尚不存在.我甚至在模块A中将符号标记为extern,但这也没有用.

是否可以在加载模块A后延迟加载符号,但在加载B或C之前它仍然不存在?

解决方法

这种情况通常使用回调来解决.

假设模块A导出函数注册/取消注册回调. B和/或C使用这些函数并向A提供适当的回调.当需要时,A检查回调是否已设置并调用它们.

像这样的东西(为简单起见,没有错误处理和锁定):

  1. /* Module A */
  2. struct a_ops /* Better to define struct a_ops in a header file */
  3. {
  4. void (*needed_func)(void);
  5. void (*another_needed_func)(void);
  6. };
  7. ...
  8. struct a_ops ops = {
  9. .needed_func = NULL;
  10. .another_needed_func = NULL;
  11. };
  12. ...
  13. int a_register_needed_funcs(struct a_ops *a_ops)
  14. {
  15. ops.needed_func = a_ops->needed_func;
  16. ops.another_needed_func = a_ops->another_needed_func;
  17. }
  18. EXPORT_SYMBOL(a_register_needed_funcs);
  19.  
  20. void a_unregister_needed_funcs()
  21. {
  22. ops.needed_func = NULL;
  23. ops.another_needed_func = NULL;
  24. }
  25. EXPORT_SYMBOL(a_unregister_needed_funcs);
  26.  
  27. ...
  28. /* Call the specified callbacks when needed: */
  29. void do_something(void)
  30. {
  31. if (ops.needed_func != NULL) {
  32. ops.needed_func();
  33. }
  34. else {
  35. /* the callback is not set,handle this: report error,ignore it or
  36. * do something else */
  37. ...
  38. }
  39. }
  40. ...
  41.  
  42. /* Modules B and C */
  43. /* Their code #includes the file where struct a_ops is defined.
  44. * The module registers the callbacks,for example,in its init function
  45. * and unregister in exit function. */
  46. ...
  47. static void func(void)
  48. {
  49. ...
  50. }
  51.  
  52. static void another_func(void)
  53. {
  54. ...
  55. }
  56.  
  57. struct a_ops my_funcs = {
  58. .needed_func = func;
  59. .another_needed_func = another_func;
  60. };
  61.  
  62. int __init my_module_init(void)
  63. {
  64. ...
  65. result = a_register_needed_funcs(&my_funcs);
  66. ...
  67. }
  68. void __exit my_module_exit(void)
  69. {
  70. ...
  71. a_unregister_needed_funcs();
  72. ...
  73. }

这类似于文件操作和内核中的许多其他回调操作.假设用户想要读取由自定义驱动程序维护的字符设备.内核本身(确切地说是VFS)接收请求但不能自己处理它.它将请求转发给已为该设备注册文件操作回调的自定义驱动程序.反过来,驱动程序使用内核正确导出的函数,如cdev_add()等.

猜你在找的Linux相关文章