Raw-OS源码分析之软件定时器

来源:互联网 发布:网络运维服务承诺书 编辑:程序博客网 时间:2024/06/07 00:22

        分析的内核版本截止到2014-04-15,基于1.05正式版,blogs会及时跟进最新版本的内核开发进度,若源码注释出现”???”字样,则是未深究理解部分。

        Raw-OS官方网站:http://www.raw-os.org/

        Raw-OS托管地址:https://github.com/jorya/raw-os/

 

        看过内核中互斥量这些变态代码之后,来看看简单的代码找找自信吧,这节,软件定时器,还记得讲任务轮转的时候的ticks计数在内核实现的原理没,先回顾一下任务tick计数的一些细节,然后再看下面的文字。

        那么首先,在系统初始化的时候讲过,Raw-OS有一个任务优先级别是5的软件定时器任务,当没有任务的优先级高于5时,内核就会轮转到这个任务,执行这个任务的任务函数,在系统初始化阶段,软件定时器的任务初始化函数是raw_timer_init(),这个软件定时器任务的建立函数就不展开了,很容易懂,接下来我们来展开软件定时器任务的任务函数timer_task(),详细解说一下。

 

 

 

        看完上面这个图,你会发现软件定时器的原理非常像tick计数的实现,其实道理上也是一样的,无非是当timer调度,任务函数执行,更新计数,判断有没有定时器计数完,执行定时器注册的回调函数,判断定时器计数形式,重新加入到timer list或者自删除。软件定时器的核心就是timer任务的任务函数

 

void timer_task(void *pa){RAW_U16 position;LIST *timer_head_ptr;LIST *iter;LIST *iter_temp;RAW_TIMER*timer_ptr;/*reset the timer_sem count since it may not be 0 at this point, make it start here*/raw_semaphore_set(&timer_sem, 0);pa = pa;while (1) {/* * 因为在call_timer_task()函数内释放系统软件定时器任务的信号量,这里获取此信号量 * 执行完timer时间更新后,系统定时器任务将会再次阻塞在此信号量上,等待下次call_timer_task()释放 */raw_semaphore_get(&timer_sem, RAW_WAIT_FOREVER);/* 禁止系统调度 */raw_disable_sche();/* 更新系统软件定时器全局计数器 */raw_timer_count++;/* 模x后计算出超时可能发生的timer_head[x]位置,这个和寻找tick_head[x]的原理一样,参考tick_list_update()函数注释 */position = (RAW_U16)(raw_timer_count & (TIMER_HEAD_NUMBERS - 1) );timer_head_ptr  = &timer_head[position];/* timer_head[x]中都是按从小到大的超时时间排序的,所以取出timer_head[x]的第一项即可 */iter = timer_head_ptr->next;while (RAW_TRUE) {/* 判断在timer_head[x]是否存在timer超时的等待项,如果不存在时,timer_head_ptr->next是指向timer_head[x]的,即是定时器链表的第一项 */if (iter != timer_head_ptr) {/* 取出timer_head[x]的第二项,因为第一项会超时删除信息,留作更新信息的目的 */iter_temp = iter->next;/* 计算出timer_head[x]第一项的任务控制块地址 */timer_ptr =  list_entry(iter, RAW_TIMER, timer_list);/* 比较系统timer全局计数器和任务超时时间点,相等时timer就超时 */if (raw_timer_count == timer_ptr->match) {/* 从系统软件定时器链表timer_head[x]中删除定时器信息 */timer_list_remove(timer_ptr);/* 如果创建timer控制块时指定了超时时间间隔,那么就会重新插入到模x之后的timer_head[%x]位置中 */if (timer_ptr->reschedule_ticks) {/* 重置定时器剩余超时时间间隔 */timer_ptr->remain = timer_ptr->reschedule_ticks;/* 重置定时器超时时间点 */timer_ptr->match  = raw_timer_count + timer_ptr->remain;/* 模x寻找timer_head[%x]位置 */position   = (RAW_U16)(timer_ptr->match & (TIMER_HEAD_NUMBERS - 1));timer_ptr->to_head = &timer_head[position];/* 按超时时间间隔大小插入到timer_head[%x]链表的适当位置 */timer_list_priority_insert(&timer_head[position], timer_ptr);}/* 如果没有指定超时时间,即timer为一次性计时性质,超时后设置为deactive状态 */else {timer_ptr->timer_state = TIMER_DEACTIVE;}/*Any way both condition need to call registered timer function*//*the registered timer function should not touch any timer related API,otherwise you get deadlock*//* 超时后timer马上执行注册的timer回调函数,传入参数为raw_timeout_param */if (timer_ptr->raw_timeout_function) {timer_ptr->raw_timeout_function(timer_ptr->raw_timeout_param);}/* 超时后,timer_head[x]的第1项会被删除,更新timer_head[x]的第2项为第1项 */iter  = iter_temp;}else {break;}}/*exit because timer is not exit*/else {break;}}/* 开启系统调度 */raw_enable_sche();}}


        然后剩下的包括定时器创建、激活、删除、反激活、更改定时周期都是一些基本和辅助功能,这里不展开了,都是很简单的代码,或者可以向我要注释版的内核代码~

 

 

 

0 0
原创粉丝点击