操作系统进程的状态以及进程状态的转换
进程是程序的一次执行活动,它是一种动态的概念,而这种动态在宏观上表现为状态的变化。进程在运行中,有三种基本状态:
l 运行态:进程分配到处理机运行。
l 就绪态:进程已经可以在处理机上运行,只是暂时没有分配到处理机。
l 阻塞态:进程因等待某一个事件发生而暂时不能调度上处理机运行。
一个系统中的进程在一定条件下可以在这三种状态之间转换。一般有四种类型的转换。
l 运行态 -> 就绪态
进程占用CPU运行了一段时间,但是没有运行结束。为使各就绪进程能比较平衡地共享CPU,此时调度程序需要将其它就绪进程调度上处理机运行,于是原来占据处理机的进程成为就绪态,等待下一次被调度上处理机运行。
l 就绪态 -> 运行态
进程处于就绪态,调度程序总是有机会将其调度上处理机,于是该进程从就绪态转为运行态,并从上一次运行的中断点继续运行。
l 运行态 -> 阻塞态
进程运行过程中可能因等待某种事件发生而暂时停止,比如等待一次键盘事件或者磁盘输入输出。进程进入阻塞态时,调度程序会调度一个就绪态进程上处理机运行。
l 阻塞态 -> 就绪态
当进程进入阻塞态之前等待发生的事件业已发生,则该进程从阻塞态转为就绪态,于是它可以再被调度上处理机继续运行。
除了个别进程外,一般进程都需要经历这三种状态,并在这三种状态中反复变换直至运行终止。
Nachos进程的状态以及进程状态的转换
Nachos中系统线程和用户进程
Nachos为线程提供的功能函数有:
1. 生成一个线程(Fork)
2. 使线程睡眠等待(Sleep)
3. 结束线程(Finish)
4. 设置线程状态(setStatus)
5. 放弃处理机(Yield)上面这5个方法对于我们实现自己selftest方法来说是必须掌握的。
Nachos系统结构
Nachos线程管理同实际进程管理的不同
Nachos除了在线程管理上作了一系列的简化外,和实际的进程管理还有以下的不同:
l 不存在系统中所有线程的列表
在一般的操作系统中,进程的数目总是有限的,但是Nachos中的线程数目可以是无限的(当然,用户进程的数目应该也是有限的。当虚拟机内存以及虚拟内存都耗尽时,就不能产生新的用户线程)。这是因为,线程的控制结构和系统线程的运行是占用宿主机的。能够开多少线程完全由宿主机条件限制,理论上是无限的。
l 线程的调度比较简单
在启动了时钟中断的情况下,当时钟中断到来时,如果就绪线程队列中有就绪线程,就必须进行线程切换;当没有启动时钟中断的情况下,Nachos使用非抢占式调度。
l 没有实现父子线程的关系
可以说,所有的Nachos线程都是Nachos的一个子线程。但是Nachos线程之间的父子关系没有实现。这样产生的混乱体现在线程的空间释放上,一个线程空间的释放是由下一个被切换的线程也即兄弟线程进行的,而这两个线程可以是没有任何关系的。这样的情况对以后进一步进行系统扩充是不利的。
没有实现父子线程关系这点很重要!!!这直接导致了fork函数跟我们正常操作系统中的巨大差异:
简单来说Nachos的fork就是将创建的线程加入到ready队列当中,但是Linux的fork函数描述是:内核根据父进程复制出一个子进程,父进程和子进程的PCB信息相同,用户态代码和数据也相同。因此,子进程现在的状态看起来和父进程一样,做完了初始化,刚调用了fork进入内核,还没有从内核返回。
Nachos线程转换图