手机版
你好,游客 登录 注册
背景:
阅读新闻

练习使用 __attribute__ 属性(仿照内核)

[日期:2019-02-23] 来源:Linux社区  作者:GyForever1004 [字体: ]

上一篇文章分析了内核中各种 initcall 的调用过程,在这个基础上大概掌握了内核中使用的这种方法,于是参考内核及网友的文章自己动手写了下,记录在这个随笔中。

源代码如下:

#include <unistd.h>
#include <stdint.h>
#include <stdio.h>

typedef void (*myown_call)(void);

/* 引用 LDS 文件中的标识 */
extern myown_call _myown_start[];
extern myown_call _myown_end[];

/* 宏定义 */
#define _init __attribute__((unused, section(".myown")))
#define func_init(func) myown_call _fn_##func _init = func

/* 随便定义三个函数 */
static void func1(void)
{
    write(1, "function one!\n", 14);
}

static void func2(void)
{
    write(1, "function two!\n", 14);
}

static void func3(void)
{
    write(1, "function three!\n", 16);
}

/* 定义函数函数指针 */
func_init(func1);
func_init(func2);
func_init(func3);

/* 定义的展开:
static myown_call _fn_func1 __attribute__((unused, section(".myown"))) = func1;
*/

/* 依次调用段内的函数 */
void do_initcalls(void)
{
    myown_call *call_ptr = _myown_start;

    do {
            fprintf (stderr, "call_ptr: %p\n", call_ptr);
            (*call_ptr)();
            ++call_ptr;

    } while (call_ptr < _myown_end);

}

int main(void)
{
    do_initcalls();

    return 0;
}

 其中 __attribute__((unused)) 表示该函数或变量可能不使用,这个属性可以避免编译器产生警告信息。

OK,源代码如上所示,接下来就要编译。

我们需要修改默认的 LDS 文件,通过

ld -verbose > demo.lds

命令导出链接器脚本文件。

修改 LDS,添加如下代码:

_myown_start = .;
.myown  : { *(.myown) }
_myown_end = .;

然后编译即可:

gcc -o test -Tdemo.lds test.c

成功生成 test 可执行文件后运行。

运行结果如下:

我们也可以能过如下命令来查看自定义段内的数据信息:

objdump -d -j .myown test

数据信息如下:

OK,这篇文章到此结束,成功仿照内核完成了函数的调用。其实这也或许是在练习 C 语言中 attribute 属性的用法。

感谢您的浏览!

Linux公社的RSS地址https://www.linuxidc.com/rssFeed.aspx

本文永久更新链接地址https://www.linuxidc.com/Linux/2019-02/157049.htm

linux
相关资讯       __attribute__ 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款