当前位置: 首页 > news >正文

rtthread - V5.1.0版本 HOOK 钩子函数总结

rtthread - V5.1.0版本 钩子函数 相对于V4.0.3版本做了很大的修改和优化:

旧版本 V4.0.3:

   rt_thread_inited_sethook(thread_inited_hook);rt_thread_deleted_sethook(thread_deleted_hook);rt_scheduler_sethook(scheduler_hook);

新版本 V5.1.0:

    rt_thread_inited_sethook(&init_hook_node);rt_object_detach_sethook(obj_detach_hook);rt_scheduler_sethook(scheduler_hook);

在RT-Thread V5.1.0版本中,删除线程的回调钩子函数(hook)机制主要围绕宏定义配置:

// overflow hook
#define RT_USING_OVERFLOW_CHECK// hook list
#define RT_USING_HOOK
#define RT_HOOK_USING_FUNC_PTR
#define RT_USING_HOOKLIST// idle thread
#define RT_USING_IDLE_HOOK
#define RT_IDLE_HOOK_LIST_SIZE 4
#define IDLE_THREAD_STACK_SIZE 2048

函数实现:相关rtthread 单元测试例程:

我自己写的项目应用:

extern void rt_thread_inited_sethook(rt_thread_inited_hooklistnode_t node);static void thread_inited_hook(rt_thread_t thread)
{rt_kprintf("current thread name: [%s], Object created. \n", thread->parent.name);
}RT_OBJECT_HOOKLIST_DEFINE_NODE(rt_thread_inited, init_hook_node, thread_inited_hook);static void obj_detach_hook(struct rt_object *object)
{rt_kprintf("current thread name: [%s], Object deleted. \n", object->name);struct rt_timer*  timer  = rt_container_of(object, struct rt_timer,  parent);struct rt_thread* thread = rt_container_of(timer,  struct rt_thread, thread_timer);rt_free((void*)thread->user_data);thread->user_data = RT_NULL;
}void hook_init(void)
{rt_thread_inited_sethook(&init_hook_node);rt_object_detach_sethook(obj_detach_hook);
}

线程创建时,会自动把hook链表进行初始化赋值,并在运行时检测和满足条件时调用钩子函数:

栈溢出钩子

宏定义配置:

/* 栈保护方式选择(二选一) */
#define RT_USING_OVERFLOW_CHECK      // 启用软件栈溢出检查(硬件保护不足时使用)
// #define RT_USING_HW_STACK_GUARD   // 启用硬件栈保护(推荐)/* 栈生长方向配置(根据 CPU 手册设置) */
#define ARCH_CPU_STACK_GROWS_UPWARD     // 栈向上生长:RAM低地址增长(如 ARM Cortex-M) 
// #undef ARCH_CPU_STACK_GROWS_UPWARD   // 栈向下生长(如 x86)

若选择软件栈溢出检查,确保 rt_scheduler_stack_check 函数逻辑与栈生长方向一致:

钩子注册方式 - 插入代码块 和 函数指针

RT-Thread V5.1.0支持两种钩子注册方式,编译时插入代码块 优先级高于 函数指针方式

(1)接口注册:函数指针方式(动态注册)

  • 机制
    通过全局函数指针注册钩子,例如线程删除时触发:

// 声明钩子函数指针(object.c)
static void (*rt_object_detach_hook)(struct rt_object *object);// 注册钩子函数
void rt_object_detach_sethook(void (*hook)(struct rt_object *object)) {rt_object_detach_hook = hook;
}
  • 使用示例
    用户需在代码中调用rt_object_detach_sethook注册回调:

void my_detach_hook(struct rt_object *obj) {// 自定义逻辑,如资源释放
}// 初始化时注册
rt_object_detach_sethook(my_detach_hook);

(2)锚点:编译时插入代码块(精细控制)

  • 机制
    rtconfig.h中通过宏定义直接插入代码到锚点位置,例如调度器钩子:

// 定义锚点插入宏(rtconfig.h)
#define __on_rt_scheduler_hook(from, to) \my_scheduler_notifier(from, to)  // 替换为自定义函数// 需提前声明函数原型
extern void my_scheduler_notifier(struct rt_thread *from, struct rt_thread *to);

(3)线程删除与钩子触发

  • 删除线程接口
    使用rt_thread_delete删除线程时,系统会释放资源并触发相关钩子:

    rt_err_t rt_thread_delete(rt_thread_t thread);
  • 钩子触发流程

    1. 线程删除时调用rt_object_detach(内核对象分离)。
    2. 若配置了RT_USING_HOOK,触发rt_object_detach_hook
    3. 若使用编译时插入方式,执行用户定义的代码块(如调度器切换通知)。
// rtconfig.h 中启用钩子并配置
#define RT_USING_HOOK
#define RT_HOOK_USING_FUNC_PTR  // 可选,启用函数指针方式// 编译时插入调度器钩子(rtconfig.h)
#define __on_rt_scheduler_hook(from, to) \my_thread_delete_hook(from, to)extern void my_thread_delete_hook(struct rt_thread *from, struct rt_thread *to);

锚点位置__on_后面函数名字,是固定的和rtthread有关?还是任何名字都可以?

在 RT-Thread V5.1.0 中,锚点位置 __on_ 后面的函数名字是固定的,与 RT-Thread 内核的预定义锚点名称强相关。用户不能随意自定义该部分名称,否则可能导致钩子机制失效。

(1)锚点名称的固定性

  • 内核预定义锚点
    RT-Thread 内核在关键代码位置(如线程调度、对象操作等)预定义了锚点名称,例如:

    // 调度器切换线程的锚点
    RT_DEFINE_HOOK(rt_scheduler_hook, void(struct rt_thread *from, struct rt_thread *to));

    这里的 rt_scheduler_hook 是内核定义的锚点名称,用户必须严格遵循此名称。

  • 用户宏定义规则
    用户需在 rtconfig.h 中通过 #define __on_<锚点名称>(参数列表) 的格式重定义锚点,例如:

    #define __on_rt_scheduler_hook(from, to) my_scheduler_notifier(from, to)

    其中 rt_scheduler_hook 必须与内核预定义的锚点名称完全一致。

RT-Thread V5.1.0 锚点钩子函数列表

锚点名称用途配置示例
rt_scheduler_hook线程调度器切换线程时触发#define __on_rt_scheduler_hook(from, to) my_scheduler_notifier(from, to)
rt_object_attach_hook内核对象(如线程、信号量)添加到对象管理器时触发#define __on_rt_object_attach_hook(obj) my_obj_attach_hook(obj)
rt_object_detach_hook内核对象从对象管理器移除时触发#define __on_rt_object_detach_hook(obj) my_obj_detach_hook(obj)
rt_object_trytake_hook线程尝试获取内核对象(如信号量)时触发#define __on_rt_object_trytake_hook(obj) my_trytake_hook(obj)
rt_object_take_hook线程成功获取内核对象后触发#define __on_rt_object_take_hook(obj) my_take_hook(obj)
rt_object_put_hook线程释放内核对象时触发#define __on_rt_object_put_hook(obj) my_put_hook(obj)
rt_malloc_hook从堆内存分配内存块时触发#define __on_rt_malloc_hook(ptr, size) my_malloc_hook(ptr, size)
rt_free_hook释放堆内存块时触发#define __on_rt_free_hook(ptr) my_free_hook(ptr)
rt_mp_alloc_hook从内存池分配内存块时触发#define __on_rt_mp_alloc_hook(mp, block) my_mp_alloc_hook(mp, block)
rt_mp_free_hook释放内存池内存块时触发#define __on_rt_mp_free_hook(mp, block) my_mp_free_hook(mp, block)
rt_interrupt_enter_hook进入中断时触发#define __on_rt_interrupt_enter_hook() my_irq_enter_hook()
rt_interrupt_leave_hook退出中断时触发#define __on_rt_interrupt_leave_hook() my_irq_leave_hook()
rt_timer_timeout_hook定时器超时时触发#define __on_rt_timer_timeout_hook(timer) my_timer_hook(timer)
rt_thread_inited_hook线程初始化完成后触发#define __on_rt_thread_inited_hook(thread) my_thread_init_hook(thread)
rt_thread_suspend_hook线程挂起时触发#define __on_rt_thread_suspend_hook(thread) my_suspend_hook(thread)
rt_thread_resume_hook线程恢复时触发#define __on_rt_thread_resume_hook(thread) my_resume_hook(thread)

注意事项

  • 锚点名称必须与内核定义一致,否则钩子无法生效。
  • 插入宏优先级高于函数指针,同时使用时插入宏会覆盖函数指针。
  • 避免在钩子函数中执行阻塞操作(如 rt_thread_delay),否则可能导致系统异常。
  • 头文件管理:建议在 rtconfig.h 中包含用户钩子头文件,或通过编译选项(如 -include user_hook.h)引入。

http://www.dtcms.com/a/282948.html

相关文章:

  • VUEX 基础语法
  • BBDM: Image-to-image Translation with Brownian Bridge Diffusion Models 译读笔记
  • 汽车电子功能安全标准ISO26262解析(二)——需求部分
  • 使用JS编写一个购物车界面
  • 51c大模型~合集155
  • 求不重叠区间总和最大值
  • 【Linux】基本指令学习1
  • 【从树的视角理解递归】【递归 = 遍历 || 分解】
  • 薄板样条(TPS, Thin Plate Spline)数学原理推导
  • 从0到1开发网页版五子棋:我的Java实战之旅
  • 【ROS/DDS】FastDDS:C++编写一个发布者和订阅者应用程序(三)
  • OpenCV稠密光流估计的一个类cv::optflow::DenseRLOFOpticalFlow
  • hashMap原理(一)
  • FAISS深度学习指南:构建高效向量检索系统的完整方法论
  • SSH连接复用技术在海外云服务器环境下的稳定性验证与优化方案
  • [时序数据库-iotdb]时序数据库iotdb的安装部署
  • 【C++】迭代器
  • 第五章 管道工程 5.4 管道安全质量控制
  • 【前端】HTML语义标签的作用与实践
  • 想删除表中重复数据,只留下一条,sql怎么写
  • 1688商品API全链路开发实践
  • Reddit Karma是什么?Post Karma和Comment Karma的提升指南
  • 搭建基于Gitee文档笔记自动发布
  • 达梦数据库配置兼容MySQL
  • Vue + Element UI 实现单选框
  • [特殊字符] 第1篇:什么是SQL?数据库是啥?我能吃吗?
  • LeafletJS 进阶:GeoJSON 与动态数据可视化
  • UI测试平台TestComplete:关键字驱动测试技巧
  • 【ArcGISPro】修改conda虚拟安装包路径
  • Mybatis的SQL编写—XML方式