从4.1.0版本开始,RT-Thread在保证向前兼容的基础上对原有的HOOK方式进行了改进,实现了如下的效果:
RT_USING_HOOK
作为总开关在rtconfig.h
定义宏开关RT_USING_HOOK
将开启HOOK功能。默认情况下,在该宏未定义时,所有HOOK功能都将被强制关闭,不会生成任何代码。
在4.1.0之前,RT-Thread提供了一套基于函数指针运行时注册的HOOK机制。新版本中,在开启HOOK功能的前提下,定义宏开关RT_HOOK_USING_FUNC_PTR
将开启与过去相同的基于函数指针运行时注册的HOOK机制,实现向前兼容。
需要特别说明的是:
无论用户是否定义了宏RT_HOOK_USING_FUNC_PTR
,新的HOOK机制都允许用户“定点”、“精细”的对RT-Thread的任意锚点进行HOOK。具体方法为:在rtconfig.h
(或其直接、间接包含的头文件)中按照如下的格式定义插入宏:
#define __on_<锚点名称>(<形参列表>) \
do { \
/* 你要插入的任意代码 */ \
} while(0)
以内核的调度锚点rt_scheduler_hook
为例,它的"等效"函数原型如下:
void __on_rt_scheduler_hook(struct rt_thread *from, struct rt_thread *to);
因此,我们只需要在rtconfig.h
(或其直接、间接包含的头文件)中定义如下的宏:
#define __on_rt_scheduler_hook(__from, __to) \
do { \
/* 你要插入的任意代码 */ \
} while(0)
就可以将任意代码插入到锚点rt_scheduler_hook
在scheduler.c中的对应位置上。实际上,所有锚点的名称都与过去函数指针的名称相同。
除了插入代码块以外,一般插入宏会被用来将目标锚点直接替换为“对用户指定函数的调用”,比如,在上述例子中,假设用户想在调度器切换线程时调用一个指定的函数my_scheduler_notifier()
,则可以修改插入宏为:
#define __on_rt_scheduler_hook(__from, __to) \
my_scheduler_notifier((__from), (__to))
这里存在一个明显的问题,即,一般来说锚点所在的c源文件并不知道用户目标函数的原型(function prototype),因此编译器会报告"implicit function declaration" 一类的警告,甚至会将其视作编译错误。为了避免这类情况的发生,我们可以在定义插入宏时顺便引入对应的函数原型:
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))
rtconfig.h
也不推荐在其中添加额外的代码:比如用户函数的原型等等。为了解决这一问题,通常有两个方案:rtconfig.h
中包含一个专门存放用户HOOK的头文件,比如:
//! rtconfg.h
...
#include “user_hook.h”
-include "<头文件>"
的方式:
-include "user_hook.h"
在arm compiler 5中使用--preinclude=头文件
的方式:
--preinclude="user_hook.h"