刚开始学习RT-Thread定时器管理时,对系统初始化rtthread_startup()函数中的rt_system_timer_init()和rt_system_timer_thread_init()这两个和定时器有关的初始化函数功能不太了解,特别是两个函数中分别新建的rt_timer_list和rt_soft_timer_list这两个列表功能是什么不明白,现在在这里写一下个人见解,如有错误欢迎指正。
先说一个我的错误思路:最开始我以为rt_timer_list是管理硬件定时器列表,rt_soft_timer_list用来管理软件定时器列表,后面发现我错了,因为硬件定时器照理来说会引发中断,且精度一般远大于时间节拍,因此是不能被RT-Thread管理的;
我的改正思路:由于RT-Thread每一个线程都会有一个自带的软件定时器,当在线程中使用操作系统延时函数时会启动该线程软件定时器进行计时,所以rt_timer_list是用于管理线程软件定时器,rt_soft_timer_list则是用于管理用户自定义的软件定时器;
证明:
首先rt_soft_timer_list是用于管理用户自定义的软件定时器这一点根据下面的代码可以看出,因为有一个RT_USING_TIMER_SOFT宏是由用户在内核中进行手动开启/关闭的
然后看看rt_timer_list的作用,首先看任务创建(动态/静态)函数中都调用了_rt_thread_init()函数,而该函数中有初始化线程定时器函数:
同时线程控制块中也有对应定义:
因此我们可以确定每个线程都有一个线程软件定时器,我们再看看线程中经常会用到的延时函数rt_thread_sleep()中的函数实现有调用rt_timer_start(),
接下来我们看看rt_timer_start()函数的部分代码,如下:
该函数作用大概就是激活一个软件定时器,并把该定时器插入到对应的定时器管理列表中,并设置其超时时间。我们看下面有一个#ifdef RT_USING_TIMER_SOFT宏,如果该定时器是用户自定义的软件定时器就插入rt_soft_timer_list,否则插入rt_timer_list,那rt_thread_sleep()挂起线程肯定不是插入rt_soft_timer_list,那只能是插入rt_timer_list,再结合线程自带的软件定时器,我们就能得出rt_timer_list是用于管理线程软件定时器;
/*******************关于软件定时器RT_TIMER_SKIP_LIST_LEVEL宏的作用*****************/
刚刚我们讲了RT-Thread把系统的软件定时器分为线程软件定时器和用户自定义软件定时器,并分别用一个列表来管理,那初始化时下面这个for循环是做什么的呢?
说实话下面这个图定义rt_timer_list[]的注释/* hard timer list*/有点让人误解是管理硬件定时器的,但我刚刚的分析认为这个其实也是管理软件定时器列表的,不过是线程软件定时器;这个hard timer list我认为可能的意思是,该类线程软件定时器的回调函数是发生在Systick硬件定时器中断中的,而自定义软件定时器回调函数是发生在软件定时器线程中的;
这个for循环和RT_TIMER_SKIP_LIST_LEVEL宏其实涉及到一个定时器跳表的概念,跳表是一种基于并联链表的数据结构,跳表是链表的一种,但它在链表的基础上增加了 “跳跃” 功能,正是这个功能,使得在查找元素时,跳表能够提供 O(log n)的时间复杂度;
例如:一个有序的链表,如下图所示,从该有序链表中搜索元素 {13, 39},需要比较的次数分别为 {3, 5},总共比较的次数为 3 + 5 = 8 次。
用跳表算法后可以采用类似二叉搜索树的方法,把一些节点提取出来作为索引,在这个结构里把 {3, 18,77} 提取出来作为一级索引,这样搜索的时候就可以减少比较次数了,得到如下图所示的结构:
在搜索的时候就减少比较次数,提升查找的效率,这是一种通过 “空间来换取时间” 的算法,在 RT-Thread 中通过宏定义 RT_TIMER_SKIP_LIST_LEVEL 来配置跳表的层数,默认为 1,表示采用一级有序链表图的有序链表算法,每增加一,表示在原链表基础上增加一级索引。
我们把包含所有定时器的链表叫做0层链表,定时器索引链表为1层或者2层...链表,那么我们应该如何确定索引链表中应该包含哪些定时器呢?这是由rtthread内核的定时器模块自己通过算法决定的,我们不需要管,该算法实现应该在下图rt_timer_start(rt_timer_t timer)函数中,我没细看(太垃圾了感觉看不懂,希望有大神发一个该算法的解析文章喂我嘴里,哈哈)
至此关于RT-thread的定时器管理的部分介绍就完成了,主要说明了rt_timer_list和rt_soft_timer_list的功能,还介绍了RT_TIMER_SKIP_LIST_LEVEL宏的功能,引入了跳表算法的概念;