新建态: 操作系统已经分配了资源给进程了。 就绪态: 已经具备了执行的所有必有的条件,但是由于各种原因,暂时无法运行,进程进入就绪状态。 运行状态: 当进程处于调度队列当中的时候就处于运行状态。 阻塞状态: 当执行进程时,遇到代码中有scanf的时候,但是又迟迟没有接收到键盘的信息的时候,这时候会出现阻塞状态,当重新接收到键盘信息的时候,这时候会重新回到就绪态,马上到运行态。 终止态: 当一个程序运行完了的时候这个进程就进入终止态。
这一系列状态到底是如何完成的呢?
操作系统会提供一个运行队列用来运行这些进程,为了后续讲解,首先应该先了解一下下面的概念:
当上面的运行队列的队首的进程运行完一个时间片之后会被抽离出来然后插入到队列尾运行下一个进程,这样循环往复。并发就是这样循环往复的一个过程。
在操作系统的下层有很多硬件设备与操作系统交互,当遇到scanf的时候,如果迟迟得不到键盘的信息,这时候不会连入到运行队列尾,而是连入到struct_device队尾,这里struct_device中存在一个wait_queue用来存储等待的进程。等待对应的硬件准备好后,就可以重新排入到运行队列中了。 所以等待的本质就是将进程的PCB连入到对应的硬件的队列当中。
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
上面就是Linux中进程的七种状态。
我们写一段死循环代码:
#include<stdio.h>
#include<unistd.h>
int main()
{
int count=0;
while(1)
{
//scanf("%d",&count);
// printf("hello world,cnt : %d \n",count);
//sleep(1);
}
return 0;
}
可以看见上面代码是R运行状态。 我们把打印加上:
可以发现状态变成了休眠状态。 为什么呢? 因为我们printf是在内存中写入,如果一直写,当缓冲区会写满,这导致显示器不是常常在线的。
S状态是可被中断的休眠状态,类似于浅睡眠
D状态是不可被中断的休眠状态,类似于深睡眠
18和19, 18进程继续,19是进程暂停。
可以看见进程被暂停了
可以看见进程处于暂停状态。
进程继续:
可以看见进程状态虽然是S但是后面少了一个+号,这是由前台进程转换为了后台进程,这时我们再在前面用ctrl+c就结束不了进程了,只能用kill来杀死后台进程(后台不能用ctrl+c来杀死)
当一个进程被追踪时,断点停下就是t状态。
x状态是死亡状态,当一个进程已经终止并且已经中系统中完全清除。
z状态是僵尸状态,与死亡状态不同,z状态是指进程已经终止但父进程还没有还没有读取其退出信息的一种状态。
通过对进程状态转换和 Linux 进程状态的分析,我们了解了操作系统如何通过不同的状态管理进程的执行。进程的三种基本状态转换解释了进程从创建到结束的生命周期,而 Linux 系统中常见的 R、S、D 等状态则细化了进程在运行、等待以及阻塞中的具体表现。这些知识不仅帮助我们理解了系统的运行机制,也为解决系统性能调优、进程管理等实际问题提供了理论基础。掌握这些进程状态,对于操作系统调试与开发者都是非常重要的一步。