找人做网站需要什么条件,专业设计企业网站,编程培训机构价格,网站开发与设计英文文献Linux内核头文件提供了一个方便的方法用来管理符号的对模块外部的可见性,因此减少了命名空间的污染(命名空间的名称可能会与内核其他地方定义的名称冲突),并且适当信息隐藏。 如果你的模块需要输出符号给其他模块使用,应当使用下面的宏定义: EXPORT_SYMBOL(name); EXPORT_SYMBO… Linux内核头文件提供了一个方便的方法用来管理符号的对模块外部的可见性,因此减少了命名空间的污染(命名空间的名称可能会与内核其他地方定义的名称冲突),并且适当信息隐藏。 如果你的模块需要输出符号给其他模块使用,应当使用下面的宏定义: EXPORT_SYMBOL(name); EXPORT_SYMBOL_GPL(name); //只适用于包含GPL许可权的模块 这两个宏均用于将给定的符号导出到模块外. _GPL版本的宏定义只能使符号对GPL许可的模块可用。 符号必须在模块文件的全局部分导出,不能在函数中导出,这是因为上述这两个宏将被扩展成一个特殊用途的声明而该变量必须是全局的。这个变量存储于模块的一个特殊的可执行部分(一个ELF段 ),在装载时内核通过这个段来寻找模块导出的变量(感兴趣的读者可以看linux/module.h获知更详细的信息)。 一、宏定义EXPORT_SYMBOL分析 1、源码 [cpp] view plaincopy include/linux/moudule.h ……. #ifndef MODULE_SYMBOL_PREFIX #define MODULE_SYMBOL_PREFIX #endif ……. struct kernel_symbol //内核符号结构 { unsignedlong value; //该符号在内存地址中的地址 constchar *name; //该符号的名称 }; …… #define __EXPORT_SYMBOL(sym,sec) \ externtypeof(sym) sym; \ __CRC_SYMBOL(sym,sec) \ staticconst char __kstrtab_##sym[] \ __attribute__((section(“__ksymtab_strings”),aligned(1))) \ MODULE_SYMBOL_PREFIX#sym; \ staticconst struct kernel_symbol __ksymtab_##sym \ __used \ __attribute__((section(“__ksymatab”sec),unused)) \ {(unsignedlong)sym,_kstrab_#sym} #define EXPORT_SYMBOL(sym) \ __EXPOTR_SYMBOL(sym,””) #define EXPORT_SYMBOL_GPL(sym) \ __EXPOTR_SYMBOL(sym,”_gpl”) #define EXPORT_SYMBOL(sym) \ __EXPOTR_SYMBOL(sym,”_gpl_future”) 在分析前先了解如下相关知识 1#运算符##运算符 通常在宏定义中使用#来创建字符串 #abc就表示字符串”abc”等。 ##运算符称为预处理器的粘合剂用来替换粘合两个不同的符号 如#define xName (n) x##n 则xName(4) 则变为x4 2gcc的 __attribute__ 属性 __attribute__((section(“section_name”)))的作用是将指定的函数或变量放入到名为”section_name”的段中。 __attribute__属性添加可以在函数或变量定义的时候直接加入在定义语句中。 如 int myvar__attribute__((section(mydata))) 0; 表示定义了整形变量myvar0;并且将该变量存放到名为”mydata”的section中 关于gcc_attribute详解可以参考http://blog.sina.com.cn/s/blog_661314940100qujt.html 2、EXPORT_SYMBOL的作用是什么 EXPORT_SYMBOL标签内定义的函数或者符号对全部内核代码公开不用修改内核代码就可以在您的内核模块中直接调用即使用EXPORT_SYMBOL可以将一个函数以符号的方式导出给其他模块使用。 这里要和System.map做一下对比System.map 中的是连接时的函数地址。连接完成以后在2.6内核运行过程中是不知道哪个符号在哪个地址的。 EXPORT_SYMBOL的符号是把这些符号和对应的地址保存起来在内核运行的过程中可以找到这些符号对应的地址。而模块在加载过程中其本质就是能动态连接到内核如果在模块中引用了内核或其它模块的符号就要EXPORT_SYMBOL这些符号这样才能找到对应的地址连接。 二、 EXPORT_SYMBOL使用方法 第一、在模块函数定义之后使用EXPORT_SYMBOL函数名 第二、在调用该函数的模块中使用extern对之声明 第三、首先加载定义该函数的模块再加载调用该函数的模块 要调用别的模块实现的函数接口和全局变量就要导出符号 /usr/src/linux-headers-2.6.32-33-generic/Module.symvers A B static int num 10; static void show(void) { printk(%d \n,num); } EXPORT_SYMBOL(show); extern void show(void); 函数A先将show() 函数导出函数B 使用extern 对其声明要注意 a -- 编译a模块后要将 Module.symvers 拷贝到b模块下 b -- 然后才能编译b模块 c -- 加载先加载a模块再加载b模块 d -- 卸载先卸载b模块再卸载a模块 三、示例代码a ,hello.c[cpp] view plaincopy #include linux/module.h static int num 10; static void show(void) { printk(show(),num %d\n,num); } static int hello_init(void) { printk(hello_init); return 0; } static void hello_exit(void) { printk(hello_exit \n); } EXPORT_SYMBOL(show); MODULE_LICENSE(GPL); module_init(hello_init); module_exit(hello_exit); 代码b show.c[cpp] view plaincopy #include linux/module.h extern void show(void); static int show_init(void) { printk(show_init); show(); return 0; } static void show_exit(void) { printk(show_exit \n); } MODULE_LICENSE(GPL); module_init(show_init); module_exit(show_exit);strong /strong 编译后加载模块卸载模块可以用 dmesg 查看内核打印信息。