分析的内核版本截止到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(); } }
然后剩下的包括定时器创建、激活、删除、反激活、更改定时周期都是一些基本和辅助功能,这里不展开了,都是很简单的代码,或者可以向我要注释版的内核代码~