snifer

[原创]Blackfin ADSP 系统之注册符号表

0
阅读(12809)

我们知道在window操作系统的一个重要的系统就是注册表,在Blackfin ADSP的操作系统UcLinux也存在一个重要的表,这个表很多时候我们叫作注册符号表。

要理解注册符号表,首先要知道在Uclinux系统中有一个非常重要的表叫内核符号表:

我们已经知道insmod是如何利用公开内核符号来解析未定义符号的了。这张表包含了实现模块化设备驱动程序所需的全局内核项――函数和变量。可以从文件/proc/ksyms中以文本的方式读取这个公开符号表

当你的模块被加载时,你声明的任何全局符号都成为内核符号表的一部分,你可以从文件/proc/ksyms或命令ksyms的结果了解这一点。

新模块可以使用你开放出来的符号,而且你在其他模块之上堆叠新模块。在主流的内核源码中也使用了这种模块堆叠的方法:msdos文件系统依赖于fat模块开放出来的符号,而ppp驱动程序则堆叠在报头压缩模块上。

在处理复杂对象时,模块堆叠非常有用。如果以设备驱动程序的形式实现一个新的抽象,它可以提供一个设备相关的插接口。比如,帧缓冲视频驱动程序可以将符号开放给下层VGA驱动程序使用。每个用户都加载帧缓冲视频驱动程序,然后在根据自己安装的设备加载相应的VGA模块。

另一种开放你的模块中的全局符号的方法是使用函数register_symtab,这个函数是符号表管理的正式接口。这里所涉及的编程接口适用于内核1.2.13和2.0。

正如函数register_symtab的名字所暗示,它用来在内核主符号表中注册符号表。这种方法要比通过静态和全局变量的方法清晰的多,这样程序员就可以把关于哪些开放给其他模块,哪些不开放的信息集中存放。这种方法比在源文件中到处堆放static声明要好的多。

如果模块在初始化过程中调用了register_symtab,全局变量就不再是开放的了;只有那些显式罗列在符号表中的符号才开放给内核。

填写一个符号表是项挺复杂的工作,但内核开发人员已经写好了头文件简化这项工作。下面若干行代码演示了如何声明和开放一个符号表:

很多筒子可能知道<linux/symtab_begin.h>,但它可是内核中最难懂的头文件之一。事实上,仅想好好使用宏X的话,根本没必要读董它。

由于register_symtab是在模块加载到内核后被调用的,它可以覆盖模块静态或全局声明的符号。此时,register_symtab用显式符号表替代模块默认开放的公共符号。

这种覆盖是可能的,因为insmod命令处理传递给系统调用sys_init_module的全局符号表,然后在调用init_module之前注册这个符号表。因此这之后的任何一次显式调用register_symtab都会替换相应模块的符号表。

如果你的模块不需要开放任何符号,而且你也不想把所有的东西都声明成static的,在init_module里加上下面一行语句就可以了。这次对register_symtab的调用通过注册一个空表覆盖了模块默认的符号表:

如果源文件不想给堆叠在其上的模块提供什么接口,用上面那行语句隐藏所有的符号总是不错的。

当模块从内核卸载时,它所声明的所有公共符号也就自动从主符号表中注销了。不过是全局符号还是显式符号表,这一点都适用。

这个问题搞清楚了对我们开发Blackfin DSP非常重要,前面说的那个基于ADI的识别系统还在进行中,遇到了很多问题,查了很多资料,终于要有些眉目了,楼上装修吵得要死,晚上还不能睡觉,要加班,啷个办喃。