EXPORT_SYMBOL出现于2.6内核,可以把内核中的函数导出到全局符号表供其他内核模块(包括用户自己写的内核模块)使用。有个限制是,这个导出的符号不能是static类型。由于需要使用内核的do_adjtimex()函数进行tick_length的调节,而这个函数在/kernel/time/ntp.c中,这里便以此为例。
首先需要在函数定义后加入“EXPORT_SYMBOL(do_adjtimex);”并且在这个c文件开头进行module.h头文件的包含(#include <linux/module.h>)。这时需要编译内核。
然后,在自己编写的内核模块用extern声明这个函数,不过我写的这个模块由于包含了<linux/timex.h>,它里面已经用extern声明过,就不必再声明了。这样就可以在内核模块中使用这个函数了。
为了确定这个函数已经导出,可以使用cat /proc/kallsyms |grep do_adjtimex来查看。
实际使用中的一个问题:2.6.35内核make内核模块时没有问题,插入时报错:Unknow symbol,而2.6.32没有遇到,这个问题没有找到解释和解决办法。(编译内核时的选项基本无区别)
其实上面这些基本很多博文中都有提到,这里顺便说下do_adjtimex()的用法。adjtimex()根据一个结构体来更改内核中相应参数,并用这个结构体来返回,它调用了do_adjtimex(),只是比后者多了从用户空间拷贝到内核空间和从内核空间拷贝到用户空间这两步。二者用法是一致的。然而有一个需要注意的地方:如果你只是需要修改某一个参数,如此例中的tick,使用tx.modes |= ADJ_TICK很有可能无效,因为非法的mode会导致执行失败。保险的用法是把mode先清零再根据需要异或,或者直接tx.modes &= ADJ_TICK。
为了验证,需要在终端运行adjtimex -p。这是个软件包,没有的话apt-get install就可以了。它能够输出相应的内核参数。