• linux 内核中EXPORT_SYMBOL()分析与实践


    linux 内核中EXPORT_SYMBOL()分析与实践

    linux内核版本 时间 备注
    4.1.15 2021/11/1 技术总结

    一、EXPORT_SYMBOL()分析

    ​ EXPORT_SYMBOL实际是一个宏函数。用于将函数或者符号向全部内核代码公开,不用修改内核代码就可以在内核模块中直接调用(注意是在内核模块中),即:使用EXPORT_SYMBOL可以将一个函数以符号的方式导出给其他模块使用。

    ​ 定义如下://出自 linux dir/include/linux/export.h文件

    #define __EXPORT_SYMBOL(sym, sec)				
    	extern typeof(sym) sym;					
    	__CRC_SYMBOL(sym, sec)					
    	static const char __kstrtab_##sym[]			
    	__attribute__((section("__ksymtab_strings"), aligned(1))) 
    	= VMLINUX_SYMBOL_STR(sym);				
    	extern const struct kernel_symbol __ksymtab_##sym;	
    	__visible const struct kernel_symbol __ksymtab_##sym	
    	__used							
    	__attribute__((section("___ksymtab" sec "+" #sym), unused))	
    	= { (unsigned long)&sym, __kstrtab_##sym }
    
    #define EXPORT_SYMBOL(sym)					
    	__EXPORT_SYMBOL(sym, "")
    

    这里以EXPORT_SYMBOL(system_state)为例,经过宏替换后结果如下:

    extern typeof (system_state) system_state;
    extern __visible void *__crc_system_state  __attribute__ ((weak));
    static const unsigned long  __kcrctab_system_state __used  __attribute__ ((section("___kcrctab" sec "+" #sym), unused))   =  (unsigned long) &__crc_system_state;
    
    static const char __kstrtab_system_state[] __attribute__((section("__ksymtab_strings"), aligned(1))) = "system_state";
    
    extern const struct kernel_symbol  __ksymtab_system_state;
        
    __visible const struct kernel_symbol   __ksymtab_system_state  __used  __attribute__ ((section("___ksymtab" sec "+" #sym), unused)) = {(unsigned long)&system_state,__kstrtab_system_state};
        
    

    以上代码实则是:对于每个使用EXPORT_SYMBOL()导出的符号,都将在ksymtab节中放置一个与之关联的结构体。

    二、实践过程记录

    创建一个module_first模块和module_second模块,再创建一个makefile文件。

    //module_first.c
    #include <linux/types.h>
    #include <linux/kernel.h>
    #include <linux/delay.h>
    #include <linux/ide.h>
    #include <linux/init.h>
    #include <linux/module.h>
    
    static int module_first_function(void)
    {
        printk("this is module_first_function
    ");
    
        return 0;
    }
    EXPORT_SYMBOL(module_first_function);  /*导出module_first_function函数供module_second模块使用 */ 
    
    static  int __init module_first_init(void)
    {
        printk("module_first_init
    ");
    
        return 0;
    } 
    
    static int __exit module_first_exit(void)
    {
        printk("module_first_exit
    ");
    
        return 0;
    }
    
    // 指定驱动的入口函数和出口函数
    module_init(module_first_init);
    module_exit(module_first_exit);
    MODULE_AUTHOR("iriczhao");
    MODULE_LICENSE("GPL");
    
    //module_second.c
    
    #include <linux/types.h>
    #include <linux/kernel.h>
    #include <linux/delay.h>
    #include <linux/ide.h>
    #include <linux/init.h>
    #include <linux/module.h>
    
    extern int module_first_function(void);
    
    static int module_second_function(void)
    {
        /* 此处调用module_first模块中module_first_function函数 */
        module_first_function();
    
        printk("============================
    ");
        printk("this is module_second_function
    ");
        printk("============================
    ");
        
        return 0;
    }
    
    static  int __init module_second_init(void)
    {
        printk("module_second_init
    ");
        module_second_function();
        return 0;
    } 
    
    static int __exit module_second_exit(void)
    {
        printk("module_second_exit
    ");
        return 0;
    }
    
    // 指定驱动的入口函数和出口函数
    module_init(module_second_init);
    module_exit(module_second_exit);
    MODULE_AUTHOR("iriczhao");
    MODULE_LICENSE("GPL");
    

    makefile 文件

    KERNELDIR := /home/iriczhao/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga
    
    CURRENT_PATH := $(shell pwd)
    
    obj-m := module_first.o module_second.o
    
    build: kernel_modules
    
    kernel_modules:
    	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
    
    clean:
    	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
    
    

    编译构建后,将生成的module_first.ko和module_second.ko两个模块文件拷贝到运行环境根文件系统中。加载模块,运行结果如下:

    可见,根据上图红框中内容显示,在module_second模块中成功调用了module_first模块中使用EXPORT_SYMBOL声明的module_first_function函数。
    image


    本文完!!!

  • 相关阅读:
    AD账号解锁
    Django中的DateTimeField格式
    接口调用,输出结果为Json格式(ConvertTo-Json),提交参数给URL(WebRequest)
    jQuery表格排序(tablesorter)
    Python脚本性能分析
    监控文件内容变化,即时写入到新文件(tail)
    导出目录权限
    多进程、多线程处理文件对比
    shell 实例收集
    DHCP : 网络世界身份的获取
  • 原文地址:https://www.cnblogs.com/iriczhao/p/15493106.html
Copyright © 2020-2023  润新知