修饰Linux驱动初始化以及逆初始化函数的宏定义详解

前言

  阅读 Linux 驱动源码时,我们发现驱动的 初始化函数逆初始化函数 总会被一个进行修饰,这个宏就决定了驱动在启动时的那个阶段执行。

  示例1:
在这里插入图片描述

#define __init                                                                 \
    __section(".init.text")                                                \
        __cold __latent_entropy __noinitretpoline __nocfi

#define __exit __section(".exit.text") __exitused __cold notrace

#define module_init(x) __initcall(x);

#define module_exit(x) __exitcall(x);

  示例2:
在这里插入图片描述

#define module_platform_driver(__platform_driver)                              \
    module_driver(__platform_driver, platform_driver_register,             \
              platform_driver_unregister)

// Expands to

static int __attribute__((__section__(".init.text"))) __attribute__((__cold__))
__attribute__((__no_sanitize__("cfi")))
rockchip_canfd_driver_init(void)
{
   
   
    return __platform_driver_register(&(rockchip_canfd_driver),
                      ((struct module *)0));
}
static void *__attribute__((__section__(".discard.addressable")))
__attribute__((
    __used__)) __UNIQUE_ID___addressable_rockchip_canfd_driver_init13 =
    (void *)&rockchip_canfd_driver_init;
asm(".section	\""
    ".initcall6"
    ".init"
    "\", \"a\"		\n"
    "__initcall__kmod_Space__12_1222_rockchip_canfd_driver_init6"
    ":			\n"
    ".long	"
    "rockchip_canfd_driver_init"
    " - .	\n"
    ".previous					\n");
;
;
static void __attribute__((__section__(".exit.text"))) __attribute__((__used__))
__attribute__((__cold__)) __attribute__((patchable_function_entry(0, 0)))
rockchip_canfd_driver_exit(void)
{
   
   
    platform_driver_unregister(&(rockchip_canfd_driver));
}
static exitcall_t __exitcall_rockchip_canfd_driver_exit
    __attribute__((__used__))
    __attribute__((__section__(".exitcall.exit"))) =
        rockchip_canfd_driver_exit;
;

  这段代码是 Linux 内核模块加载和卸载机制的一部分。它使用了一些宏和属性来确保模块在特定的阶段被正确加载和卸载。让我们逐步解析这段代码:

#define module_platform_driver(__platform_driver)                              \
    module_driver(__platform_driver, platform_driver_register,             \
              platform_driver_unregister)

  这个宏定义了 module_platform_driver,它实际上调用了 module_driver 宏,传入了平台驱动的注册和注销函数。该宏扩展后的代码:

static int __attribute__((__section__(".init.text"))) __attribute__((__cold__))
__attribute__((__no_sanitize__("cfi")))
rockchip_canfd_driver_init(void)
{
   
   
    return __platform_driver_register(&(rockchip_canfd_driver),
                      ((struct module *)0));
}
  • __attribute__((__section__(".init.text"))):将函数放置在 .init.text 段中。这个段的内容在模块加载后会被释放,以节省内存。
  • __attribute__((__cold__)):指示编译器优化器这个函数很少被调用。
  • __attribute__((__no_sanitize__("cfi"))):禁用控制流完整性(CFI)检查。
  • rockchip_canfd_driver_init:模块初始化函数,调用 platform_driver_register 注册平台驱动。
static void *__attribute__((__section__(".discard.addressable")))
__attribute__((
    __used__)) __UNIQUE_ID___addressable_rockchip_canfd_driver_init13 =
    (void *)&rockchip_canfd_driver_init;
  • __attribute__((__section__(".discard.addressable"))):将变量放置在 .discard.addressable 段中。这个段的内容在模块加载后会被丢弃。
  • __attribute__((__used__)):确保编译器不会优化掉这个变量。
  • __UNIQUE_ID___addressable_rockchip_canfd_driver_init13:一个唯一的变量名,用于防止符号冲突。
asm(".section	\""
    ".initcall6"
    ".init"
    "\", \"a\"		\n"
    "__initcall__kmod_Space__12_1222_rockchip_canfd_driver_init6"
    ":			\n"
    ".long	"
    "rockchip_canfd_driver_init"
    " - .	\n"
    ".previous					\n");
  • asm:内联汇编代码,用于在 .initcall6.init 段中插入一个初始化调用。
  • .section ".initcall6.init", "a":创建或切换到 .initcall6.init 段。
  • __initcall__kmod_Space__12_1222_rockchip_canfd_driver_init6:一个唯一的标签名。
  • .long rockchip_canfd_driver_init - .:插入初始化函数的地址。
  • .previous:返回到前一个段。
static void __attribute__((__section__(".exit.text"))) __attribute__((__used__))
__attribute__((__cold__)) __attribute__((patchable_function_entry(0, 0)))
rockchip_canfd_driver_exit(void)
{
   
   
    platform_driver_unregister(&(rockchip_canfd_driver));
}
  • __attribute__((__section__(".exit.text"))):将函数放置在 .exit.text 段中。这个段的内容在模块卸载时会被调用。
  • __attribute__((__used__)):确保编译器不会优化掉这个函数。
  • __attribute__((__cold__)):指示编译器优化器这个函数很少被调用。
  • __attribute__((patchable_function_entry(0, 0))):允许在运行时修改这个函数的入口点。
  • rockchip_canfd_driver_exit:模块卸载函数,调用 platform_driver_unregister 注销平台驱动。
static exitcall_t __exitcall_rockchip_canfd_driver_exit
    __attribute__((__used__))
    __attribute__((__section__(".exitcall.exit"))) =
        rockchip_canfd_driver_exit;
  • exitcall_t:通常是一个函数指针类型。
  • __attribute__((__used__)):确保编译器不会优化掉这个变量。
  • __attribute__((__section__(".exitcall.exit"))):将变量放置在 .exitcall.exit 段中,这个段的内容在模块卸载时会被调用。
  • __exitcall_rockchip_canfd_driver_exit:一个变量,其值为 rockchip_canfd_driver_exit 函数的地址。

这段代码的主要功能是:

  1. 注册平台驱动:在模块加载时,rockchip_canfd_driver_init 函数会被调用,注册 rockchip_canfd_driver
  2. 注销平台驱动:在模块卸载时,rockchip_canfd_driver_exit 函数会被调用,注销 rockchip_canfd_driver
  3. 段管理:使用各种段属性和内联汇编,确保初始化和卸载代码在适当的时间被调用,并且不会占用不必要的内存。

通过这些机制,Linux 内核模块可以优雅地管理和加载/卸载平台驱动程序。

上述提及的宏都定义在include/linux/init.h文件中,接下来我们一块学习下这个文件的内容。

一、include/linux/init.h

1. __initxx宏

#define __init		__section(".init.text") __cold  __laten
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小嵌同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值