点击查看《Xenomai/IPIPE源代码情景解析》
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!
6.4.1 Xenomai/Linux线程交替调度的本质
1. 典型操作系统进程状态
进程状态转换是操作系统中非常核心的概念。典型的操作系统中的进程状态如图所示,这些状态描述了一个进程在其生命周期中的不同阶段。
为了方便记忆,可以把它想象成一个瓷碗,称之为瓷碗模型。
- 创建态(New):当一个新进程刚刚被创建时,它处于创建态。此时,操作系统正在为该进程分配必要的资源和设置环境。
- 就绪态(Ready):一旦进程已经准备好可以运行,但尚未被调度到CPU上执行,它就处于就绪态。这意味着进程已经获得了除CPU时间之外的所有必要资源,并等待着被操作系统调度以获取CPU时间。
运行态(Running):当进程被分配了CPU并正在执行其指令时,它处于运行态。这是进程实际占用CPU进行计算或数据处理的状态。 - 阻塞态(Blocked):如果进程因为需要等待某个事件发生(例如I/O操作完成)而无法继续执行,则会被置于阻塞态。在这种状态下,即使给它CPU时间,它也无法执行,直到等待的事件发生。
- 终止态(Terminated):当进程完成了其任务或者由于某些原因被强制停止后,它将进入终止态。这时,操作系统会释放该进程所占用的所有资源,并清除相关的控制结构。
这些状态之间的转换是由操作系统内核根据特定的调度算法和系统事件来管理的。
2. Linux进程状态
抛掉创建态和终止态,我们来看一下Linux如何定义就绪态,运行态,阻塞态。
- (1)TASK_RUNNING(就绪态&运行态):
就绪态&运行态都用TASK_RUNNING标记。这个表示进程要么正在CPU上执行,要么在就绪队列中排队,已经准备好执行并且等待被调度器分配CPU时间。这个地方容易混淆,可是Linux说是这么设计的。 - (2)TASK_INTERRUPTIBLE(可中断阻塞态):
当一个进程正在等待某个事件发生(如I/O操作完成、信号量变为可用等),它会被置于TASK_INTERRUPTIBLE状态。这种状态下,尽管进程暂时不能继续执行,但它可以被信号中断。例如,如果一个进程正在等待磁盘读取完成,它可以响应来自外部的信号(如终止信号),从而提前退出等待状态。 - (3)TASK_UNINTERRUPTIBLE(不可中断阻塞态):
类似于TASK_INTERRUPTIBLE,但处于此状态的进程不会响应任何信号,直到它所等待的系统资源变得可用。这种情况通常出现在进程需要直接访问硬件或进行关键性的系统调用时,为了避免因信号干扰导致数据损坏或其他不稳定情况。因此,使用这种状态要非常谨慎。
3. Xenomai进程状态
抛掉创建态和终止态,我们来看一下Xenomai如何定义就绪态,运行态,阻塞态。
- (1)就绪态XNREADY
XNREADY代表已经加入到就绪队列,等待运行 - (2)运行态
图中运行态不是画错了,而是根据代码理解到的真实情况,没有专门为运行态定义一个标记。
在xnsched_run中,调用xnarch_switch_to切换到新的xnthread时,会把XNREADY标记清除掉。
xnsched_run
__xnsched_run
pipeline_schedule
___xnsched_run
next = xnsched_pick_next(sched);
thread = xnsched_rt_pick(sched);//从Multi-level priority queue取出一个thread
set_thread_running(sched, thread); //把XNREADY清除掉
pipeline_switch_to(prev, next, leaving_inband)
xnarch_switch_to(prev, next);
ipipe_switch_to(prev, next)
switch_to(prev, next, last); //完成切换
- (3)阻塞态
Xenomai定义的阻塞态,其中包括XNSUSP,XNPEND,XNDELAY,XNRELAX,XNHELD等情况。特别注意其中的XNRELAX,后面会用到。- XNSUSP (0x00000001): 表示线程被挂起。挂起状态意味着线程暂时不执行,直到它被恢复。
- XNPEND (0x00000002): 表示线程正在等待某个资源。这类似于Linux中的TASK_INTERRUPTIBLE状态,但具体实现可能有 所不同。
- XNDELAY (0x00000004): 表示线程被延迟执行。可能是由于定时器或其他机制导致线程需要在未来的某个时间点才开始运行。
- XNRELAX (0x00000080): 表示线程是迁移到了Linux运行,处于放松的状态。
- XNHELD (0x00000200): 表示线程为了处理紧急情况而被持有。这可能是为了确保关键操作不会被打断。
4. Xenomai/Linux交替调度沙漏模型
只保留Xenomai和Linux的进程状态的就绪态、运行态、阻塞态,再把Xenomai模型上下翻转,与Linux模型就构成了一个沙漏模型!
何谓交替?就是任务在Xenomai和Linux之间可以流转,可以在Linux中以tast_struct形式被调度运行,或可以在Xenomai以xnthread形式被调度运行。就像一个沙漏一样,当沙漏被上下翻转了,沙子(任务)可以流动到下方。而IPIPE就是翻转沙漏的手!
- (1)进程从Linux交替到Xenomai中运行
这个过程又称为硬化过程(可以联想到硬实时),由xnthread_harden函数实现。
它会将task_struct中的state设置为TASK_INTERRUPTIBLE状态,阻止进程在Linux中被调用。
它会将xnthread的XNRELAX标记用xnthread_resume函数清除,最终让线程将进入就绪(READY)状态 - (2)进程从Xenomai交替到Linux中运行
这个过程又称为轻松过程(可以联想到脱离硬实时),由xnthread_relax函数实现。
它会调用xnthread_suspend函数将xnthread设置为XNRELAX,阻止xnthread在Xenomai中执行。
它会清除task_struct中的TASK_INTERRUPTIBLE状态,最终让task_struct进行就绪状态。
后面的章节会展开xnthread_harden函数和xnthread_relax函数具体实现的分析。
点击查看《Xenomai/IPIPE源代码情景解析》
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!