The Kernel Symbol Table

We've seen how insmod resolves undefined symbols against the table of public kernel symbols. The table contains the addresses of global kernel items—functions and variables—that are needed to implement modularized drivers. When a module is loaded, any symbol exported by the module becomes part of the kernel symbol table. In the usual case, a module implements its own functionality without the need to export any symbols at all. You need to export symbols, however, whenever other modules may benefit from using them. 我们已经看到了 insmod 如何根据公共内核符号表解析未定义的符号。 该表包含实现模块化驱动程序所需的全局内核项(函数和变量)的地址。 加载模块时,该模块导出的任何符号都将成为内核符号表的一部分。 在通常情况下,模块实现自己的功能,根本不需要导出任何符号。 但是,只要其他模块可以从使用它们中受益,您就需要导出符号。

New modules can use symbols exported by your module, and you can stack new modules on top of other modules. Module stacking is implemented in the mainstream kernel sources as well: the msdos filesystem relies on symbols exported by the fat module, and each input USB device module stacks on the usbcore and input modules. 新模块可以使用模块导出的符号,并且您可以将新模块堆叠在其他模块之上。 模块堆叠也在主流内核源码中实现:msdos 文件系统依赖于 fat 模块导出的符号,每个输入 USB 设备模块都堆叠在 usbcore 和输入模块上。

Module stacking is useful in complex projects. If a new abstraction is implemented in the form of a device driver, it might offer a plug for hardware-specific implementations. For example, the video-for-linux set of drivers is split into a generic module that exports symbols used by lower-level device drivers for specific hardware. According to your setup, you load the generic video module and the specific module for your installed hardware. Support for parallel ports and the wide variety of attachable devices is handled in the same way, as is the USB kernel subsystem. Stacking in the parallel port subsystem is shown in Figure 2-2; the arrows show the communications between the modules and with the kernel programming interface. 模块堆叠在复杂项目中很有用。 如果以设备驱动程序的形式实现新的抽象,它可能会为特定于硬件的实现提供一个插件。 例如,video-for-linux 驱动程序集被拆分为一个通用模块,该模块导出特定硬件的较低级别设备驱动程序使用的符号。 根据您的设置,您为已安装的硬件加载通用视频模块和特定模块。 对并行端口和各种可连接设备的支持以相同的方式处理,USB 内核子系统也是如此。 并口子系统中的堆叠如图2-2所示; 箭头显示模块之间的通信以及与内核编程接口的通信。

Figure 2-2. Stacking of parallel port driver modules

When using stacked modules, it is helpful to be aware of the modprobe utility. As we described earlier, modprobe functions in much the same way as insmod, but it also loads any other modules that are required by the module you want to load. Thus, one modprobe command can sometimes replace several invocations of insmod (although you'll still need insmod when loading your own modules from the current directory, because modprobe looks only in the standard installed module directories). 使用堆叠模块时,了解 modprobe 实用程序会很有帮助。 正如我们前面所描述的,modprobe 的功能与 insmod 非常相似,但它也会加载您要加载的模块所需的任何其他模块。 因此,一个 modprobe 命令有时可以替换对 insmod 的多次调用(尽管在从当前目录加载自己的模块时仍然需要 insmod,因为 modprobe 只在标准安装的模块目录中查找)。

Using stacking to split modules into multiple layers can help reduce development time by simplifying each layer. This is similar to the separation between mechanism and policy that we discussed in Chapter 1. 使用堆叠将模块拆分为多个层可以通过简化每一层来帮助减少开发时间。 这类似于我们在第 1 章中讨论的机制和策略之间的分离。

The Linux kernel header files provide a convenient way to manage the visibility of your symbols, thus reducing namespace pollution (filling the namespace with names that may conflict with those defined elsewhere in the kernel) and promoting proper information hiding. If your module needs to export symbols for other modules to use, the following macros should be used. Linux 内核头文件提供了一种方便的方法来管理符号的可见性,从而减少命名空间污染(用可能与内核其他地方定义的名称冲突的名称填充命名空间)并促进适当的信息隐藏。 如果您的模块需要导出符号以供其他模块使用,则应使用以下宏。

EXPORT_SYMBOL(name);

EXPORT_SYMBOL_GPL(name);

Either of the above macros makes the given symbol available outside the module. The _GPL version makes the symbol available to GPL-licensed modules only. Symbols must be exported in the global part of the module's file, outside of any function, because the macros expand to the declaration of a special-purpose variable that is expected to be accessible globally. This variable is stored in a special part of the module executible (an "ELF section") that is used by the kernel at load time to find the variables exported by the module. (Interested readers can look at <linux/module.h> for the details, even though the details are not needed to make things work.) 上述任何一个宏都使给定的符号在模块外可用。 _GPL 版本使符号仅可用于 GPL 许可的模块。 符号必须在模块文件的全局部分中导出,在任何函数之外,因为宏扩展为预期可全局访问的专用变量的声明。 此变量存储在模块可执行文件的特殊部分(“ELF 部分”)中,内核在加载时使用该部分来查找模块导出的变量。 (有兴趣的读者可以查看 <linux/module.h> 的详细信息,即使这些细节并不是让事情正常工作所必需的。)

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mounter625

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值