前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊新版RT-Thread内核中的钩子

聊聊新版RT-Thread内核中的钩子

作者头像
GorgonMeducer 傻孩子
发布2022-07-30 13:51:25
7920
发布2022-07-30 13:51:25
举报
文章被收录于专栏:裸机思维

1、综述

从4.1.0版本开始,RT-Thread在保证向前兼容的基础上对原有的HOOK方式进行了改进,实现了如下的效果:

  • 与原有使用函数指针进行“运行时刻”HOOK的方式兼容,依赖原有方式进行代码插入或HOOK的模块无需修改;
  • 使用RT_USING_HOOK作为总开关
    • 当未定义该宏时,将关闭所有HOOK功能,也不再生成任何相关代码
    • 当定义该宏时,在未开启传统“函数指针HOOK”时,默认情况下也不再生成额外代码
  • 允许用户通过“插入宏的方式”在编译时刻精细控制具体HOOK哪个位置
    • 可以插入任意代码块——其中就包括函数指针、对普通函数的调用等等

2、使用方法

2.1 总开关

rtconfig.h定义宏开关RT_USING_HOOK将开启HOOK功能。默认情况下,在该宏未定义时,所有HOOK功能都将被强制关闭,不会生成任何代码。

2.2 向前兼容

在4.1.0之前,RT-Thread提供了一套基于函数指针运行时注册的HOOK机制。新版本中,在开启HOOK功能的前提下,定义宏开关RT_HOOK_USING_FUNC_PTR将开启与过去相同的基于函数指针运行时注册的HOOK机制,实现向前兼容。

需要特别说明的是:

  • 该机制的优点:在运行时刻允许用户动态修改HOOK函数;
  • 其缺点是:即便用户并未使用对应的HOOK,该机制也将生成对应的代码,并在运行时刻略微占用一些几乎可以忽略不计的CPU周期数。

2.3 使用插入宏实现定点精细HOOK

无论用户是否定义了宏RT_HOOK_USING_FUNC_PTR,新的HOOK机制都允许用户“定点”、“精细”的对RT-Thread的任意锚点进行HOOK。具体方法为:在rtconfig.h(或其直接、间接包含的头文件)中按照如下的格式定义插入宏:

代码语言:javascript
复制
#define __on_<锚点名称>(<形参列表>)   \
    do {                           \
        /* 你要插入的任意代码 */      \
    } while(0)

以内核的调度锚点rt_scheduler_hook为例,它的"等效"函数原型如下:

代码语言:javascript
复制
void __on_rt_scheduler_hook(struct rt_thread *from, struct rt_thread *to);

因此,我们只需要在rtconfig.h(或其直接、间接包含的头文件)中定义如下的宏:

代码语言:javascript
复制
#define __on_rt_scheduler_hook(__from, __to)   \
    do {                                       \
        /* 你要插入的任意代码 */                  \
    } while(0)

就可以将任意代码插入到锚点rt_scheduler_hook在scheduler.c中的对应位置上。实际上,所有锚点的名称都与过去函数指针的名称相同。

除了插入代码块以外,一般插入宏会被用来将目标锚点直接替换为“对用户指定函数的调用”,比如,在上述例子中,假设用户想在调度器切换线程时调用一个指定的函数my_scheduler_notifier(),则可以修改插入宏为:

代码语言:javascript
复制
#define __on_rt_scheduler_hook(__from, __to)   \
    my_scheduler_notifier((__from), (__to))

这里存在一个明显的问题,即,一般来说锚点所在的c源文件并不知道用户目标函数的原型(function prototype),因此编译器会报告"implicit function declaration" 一类的警告,甚至会将其视作编译错误。为了避免这类情况的发生,我们可以在定义插入宏时顺便引入对应的函数原型:

代码语言:javascript
复制
extern void my_scheduler_notifier(struct rt_thread *from, struct rt_thread *to);

#define __on_rt_scheduler_hook(__from, __to)   \
    my_scheduler_notifier((__from), (__to))

2.4 注意事项

  • 插入宏的方式优先级高于函数指针方式,即:当你同时使用两种方法对同一个锚点进行HOOK时,插入宏的方式将覆盖(Override)掉对应的函数指针HOOK。
  • RT-Thread一般不推荐用户直接修改rtconfig.h也不推荐在其中添加额外的代码:比如用户函数的原型等等。为了解决这一问题,通常有两个方案:
    • rtconfig.h中包含一个专门存放用户HOOK的头文件,比如: //! rtconfg.h ... #include “user_hook.h”
    • 在编译选项中以全局头文件包含的形式将专门存放用户HOOK的头文件引用进来,比如: 在gcc、clang和arm compiler 6中使用 -include "<头文件>"的方式: -include "user_hook.h" 在arm compiler 5中使用--preinclude=头文件的方式: --preinclude="user_hook.h"
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 裸机思维 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、综述
  • 2、使用方法
    • 2.1 总开关
      • 2.2 向前兼容
        • 2.3 使用插入宏实现定点精细HOOK
          • 2.4 注意事项
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档