内核调度
- Zephyr 内核的调度器是基于什么原则选择当前执行线程的?
总是选择优先级最高的就绪线程作为当前线程。
当多个线程优先级相同时,调度器会如何选择?
- 线程的 “就绪状态” 和 “非就绪状态” 分别指什么?哪些情况会导致线程进入非就绪状态?
有无阻塞执行的因子来区分就绪和非就绪态。
未启动、等待内核对象、等待超时服务、被挂起、已结束或终止
- 协作式线程和抢占式线程在优先级范围、执行特性上有何本质区别?如何通过动态调整优先级实现两者的转换?
协作:优先级为负数,一旦成为当前线程则一直执行直到主动释放cpu
抢占:优先级非负,运行时可以被任何更高优先级的线程或者协作式的线程抢占。
初始值优先级可以在线程启动后动态增加或减少,通过改变线程优先级可以改变线程的调度方式
- 协作式线程如果需要执行长时间计算,可能会带来什么问题?可以通过哪些方法解决?
会导致优先级高于或者等于该线程的其他所有线程的调度被延迟到一个不可接受的时间之后
解决:协作式线程可以自身间或性的放弃cpu,让其他线程得以执行,具体来说,可以 1. 调用 k_yield
,把线程放到调度器维护的优先级排列的就绪线程链表中,然后调用调度器 2. k_sleep()
使该线程在一段指定时间内变为非就绪态的线程。
- 抢占式时间片的作用是什么?其时间片大小是否可配置?当时间片结束时,调度器会对当前抢占式线程执行什么操作?
将同优先级的线程得到调度,可以配置,可以运行期间修改
时间片结束时,会检查当前线程是否可以抢占,如果可以,则对该线程隐式调用 k_yield()
,让其他同优先级的就绪线程在该线程再次被调度前得到运行。
- 调度器锁(k_sched_lock()和k_sched_unlock())的功能是什么?如果持有调度器锁的线程进入非就绪状态,再次恢复执行时锁的状态会如何变化?
抢占式线程希望在执行某个特殊的操作时不被抢占,可以使用k_sched_lock()
。临时变成协作式线程。
会把这个锁定的线程切换出去
- 线程睡眠(k_sleep())和忙等待(k_busy_wait())的核心区别是什么?分别适用于什么场景?
延迟一段时间后再执行,到达执行时间后,线程变为就绪态,然后才能再次被调度
忙等待不会交出cpu给其他线程
- 若要让某个抢占式线程在执行特定操作时不被抢占,应如何实现?操作完成后又该如何处理?
调用调度器锁
配置选项CONFIG_NUM_COOP_PRIORITIES和CONFIG_NUM_PREEMPT_PRIORITIES分别影响什么?举例说明它们如何定义线程的优先级范围。
当 ISR(中断服务程序)触发时,对当前正在执行的线程(包括协作式和抢占式)会产生什么影响?