Zephyr之RTOS学习总结
在物联网模块级别的开发中,比如执行器的实现中,常常使用bare-metal的软件架构。一来,软件运行效率高;二来,技术开发门槛也比较低。但是,随着现代物联网模块的功能越来越强大,交互的数据越来越多,代码的规模也同步上升了几个数量级。如果不引入RTOS,恐怕软件的设计难度“难于上青天”。另外一个非常重要的问题:无法很顺利的使用现在已经成熟的第三库,比如net协议,蓝牙协议等。
任务调度
RTOS里有一项重要的性能:任务调度。RTOS的价值在于很高的响应速度,而高级调度算法是其中的关键组件。单个处理器内核在任一时间只能运行单个执行线程。调度器决定哪个线程被允许在任何时间点上执行;这个线程被称为当前线程。通过在线程之间快速切换,它带来了同时执行多项任务的错觉。灵活的RTOS调度程序允许采用广泛的方法来处理优先级,尽管RTOS通常主要用于非常狭窄的应用程序集。RTOS调度程序应提供最小的中断延迟和最小的线程切换开销。这是使得RTOS与重视时间的嵌入式系统如此密切相关的原因。
- 从运行状态过渡到暂停或等待状态,例如通过k_sem_take()或k_sleep()。
- 过渡到准备状态,例如通过k_sem_give()或k_thread_start()。
- 处理完中断后返回到线程上下文
- 调用k_yield()
当线程主动发起将自身转换为暂停或等待状态的操作时,它就会进入睡眠状态。每当调度器改变了当前线程的身份,或者当前线程的执行被ISR所取代时,内核会首先保存当前线程的CPU寄存器值。当线程后来恢复执行时,这些寄存器的值会被恢复。
抢占式时间切分
抢占式线程可以执行合作性的时间切分(如上所述),或者利用调度器的时间切分能力来允许其他相同优先级的线程执行。
调度器将时间划分为一系列的时间片,这里的时间片是以系统时钟刻度来衡量的。时间片的大小是可配置的,但这个大小可以在应用程序运行时改变。
在每个时间片结束时,调度器会检查当前线程是否是可抢占的,如果是,就隐式地代表线程调用k_yield()。这给了其他相同优先级的准备好的线程在当前线程再次被调度之前执行的机会。如果没有相同优先级的线程准备好了,那么当前线程仍然保留。
优先级高于指定限制的线程不受抢占式时间切分的影响,也不会被同等优先级的线程抢占。这允许应用程序只在处理对时间不太敏感的低优先级线程时使用抢占式时间切分。
注意:内核的时间切分算法并不能确保一组同等优先级的线程获得公平的CPU时间,因为它并不衡量线程实际得到的执行时间的多少。