前言
- 通过RT-Thread内核定时器的熟悉,并根据自己的使用,发现,软件定时器的使用需要关心某些事项
- 软件定时器分为静态初始化与动态创建两种
- 软件定时器可以创建很多,分为一次性的,周期性的。
- 两个软件定时器,超时时间可以一样,同时超时,依次执行超时回调,注意超时回调中,不要过多的处理
- 一些动态申请内存的操作,可以放在
软件定时器线程
去处理,需要配置开启软件定时器线程 - 软件定时器分为系统定时器与软件定时器线程的定时器,分为两个独立的定时器链表管理,定时器超时回调函数执行的环境不一样。
- 可以让定时器在运行的中途停下来(rt_timer_stop),并修改参数,可以调用:rt_timer_control实现如修改超时时间等操作
定时器操作
静态初始化定时器
rt_timer_init
- 主要需要首先定义一个定时器对象(非定时器指针),如struct rt_timer timer;
- 静态定义的定时器,不需要判断是否为RT_NULL,因为全局静态的变量,内存是确定的。
- 静态的定时器,不需要了,可以调用:rt_timer_detach,detach后,静态的定时器对象,不会释放,可以再次初始化使用。
动态创建定时器
rt_timer_create
- 动态创建的定时器,返回为定时器对象的指针,需要判断是否为RT_NULL
- 删除动态创建的定时器,使用:rt_timer_delete,定时器对象的内存释放
使用经验
- 定时器对象,如:rt_timer_delete后,对象指针还存在(野指针),所以,可以在删除后,手动把定时器对象改为RT_NULL,确保不【重复删除】
- 定时器启动后,如再次启动,会返回失败。所以,最好管理一个是否启动的标志位,保证不【重复启动】。
- 如果没有开启软件定时器线程,初始化/创建定时器时,使用RT_TIMER_FLAG_SOFT_TIMER,无效果,依旧是定时器中断环境执行
- 每个线程创建后,都有一个线程定时器,这个线程定时器,挂在系统定时器链表上,是通过rt_timer_init初始化。
- 可以使用list_timer,查看系统的定时器。
问题与分析
- 【问题】既然有两个定时器链表,但获取下一个定时器超时的函数,
rt_timer_next_timeout_tick
,获取的是 系统定时器链表的超时。如果开启了软件定时器线程,定义了RT_TIMER_FLAG_SOFT_TIMER
,这个超时是否准确?
【答】:经过验证与内核源码的分析:准确。需要理解(1)每个线程都有一个静态的定时器,是挂在系统定时器链表上的。(2)软件定时器线程,并不是一直在跑,计算好下一个超时后,就会suspend(此时开启了一个定时器)。
- 【问题】动态申请的线程,定时器的内存空间是动态申请的,为何使用:rt_timer_init
【答】:因为整片内存虽然是动态申请的,但定时器对象是一个静态的对象。所以需要使用:rt_timer_init,线程删除时,使用:rt_timer_detach。因为整个动态申请的线程结构体一起free释放,所以,不用担心内存泄漏问题。
总结
- 使用定时器,可以参考API或官方的定时器文档
- 使用过程中主要的事项,可以多总结,对照源码调试,思路会更清晰。