由module_init()宏想到的

 
一,前言
    在开发嵌入式Linux驱动程序时,我们通常使用module_init及module_exit宏来指定一个驱动程序的入口函数和出口函数。如果驱动模块被编译并链接至内核中,内核启动的过程中会自动加载它。通过对这两个宏定义的分析,可以写出一个简化的间接地调用函数的例子,其基本的方法是通过GNU GCC支持的__attribute__扩展功能将与入口函数地址链接至ELF文件中的特定的段区,并使用链接脚本导出该段区的地址,这样就可以做到间接调用函数了。这可以视为使用C语言开发软件,模块化的一个高级方法。
 
二,GNU GCC的链接脚本
    GNU binutils的文档中指出,链接器ld中内嵌了一个默认的链接脚本,使用--verbose(或者执行ld --verbose)参数可以输出该脚本,我们把它保存到internal-ldscript.ld:

 

    在修改这个链接脚本之前,我们要确定如何修改它;而在此之前,来让我们先编写一个用于测试的C代码。
 
三,使用__attribute__将函数地址信息指定到特定的段区

    编写的测试代码如下:

 
    从图中可以看到,在main函数中没有直接地调用simple_add和simple_mul这两个函数,而是访问了两个外部的结构体符号,即mfunc_info_start和mfunc_info_end,请注意这两个是“符号”,而不是指针(指针是变量,它们两个不是变量);同时,包含simple_add和simple_mul的函数地址和名称的结构体被指定到了.data.mfunc段区。
 
四,修改链接脚本
    上图C代码中引用的两个符号mfunc_info_start和mfunc_info_end需要在链接脚本中导出,修改后的链接脚本为modified.ld,改动如下:

 

    至此,接下来我们就可以来编译了。
 
五,编译并测试
    编译时需要指定链接脚本:

 

    从图中可以看到,这样间接地调用函数是可行的。当然,Linux驱动开发使用的宏比这个要复杂得多,还要解决一些模块加载次序、依赖关系等,这就需要更深入的探究了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值