【Linux】进程(2)状态

张开发
2026/4/21 7:12:23 15 分钟阅读

分享文章

【Linux】进程(2)状态
目录一、冯诺依曼二、操作系统三、进程状态1运行状态进程已获得CPU资源正在执行指令是进程生命周期中唯一能直接操作硬件、推进任务的阶段。2阻塞状态进程因等待特定事件如打印主动放弃CPU但仍保留在内存中仅不占用CPU资源。等待的事件触发后进程可直接进入就绪态等待下一次CPU调度。3挂起状态挂起是进程的特殊挂起状态进程会被操作系统从内存换出到外存如磁盘完全不占用CPU和内存资源仅在外存保留进程映像如PCB等。前面我们已经学习了进程的基本概念在进入进程状态前我们先了解下冯诺依曼体系结构一、冯诺依曼输入设备包括键盘 鼠标等中央处理器(CPU)含有运算器和控制器、寄存器等输出设备显示器等存储器是指内存是cpu和外设之间的巨大缓冲区cpu只能对内存进行读写不能访问外设这也是进程某个状态会发生的原因。二、操作系统操作系统对下与硬件交互管理所有的软硬件资源对上为用户程序应用程序提供⼀个良好的执行环境操作系统中不止对进程有着系统的管理对底层硬件也有管理类似与对进程的管理每个外设都有对应的结构体。我们可以看出进程是在操作系统中当进程需要被启用时会先进入cpu就绪队列中等待cpu调度与执行运行完还会重新返回到操作系统中。三、进程状态这里我们细说三种比较重要的状态1运行状态进程已获得CPU资源正在执行指令是进程生命周期中唯一能直接操作硬件、推进任务的阶段。R运行状态(running)运行状态不一定在运行它表示进程要么是在运行中要么是在运行队列里。让程序一直死循环且啥都不打印就会一直处于运行状态大家来猜一下子进程是什么状态子进程一直循环打印自己的信息。#include stdio.h #include sys/types.h #include unistd.h int main() { int ret fork(); // printf(%d, ret: %d\n, getpid(), ret); if (ret 0) { while (1) { printf(I am a child, pid: %d, ppid: %d\n, getpid(), getppid()); sleep(1); } } else if (ret 0) { printf(I am a father, pid: %d, ppid: %d\n, getpid(), getppid()); while (1) { } } return 0; }2阻塞状态进程因等待特定事件如打印主动放弃CPU但仍保留在内存中仅不占用CPU资源。等待的事件触发后进程可直接进入就绪态等待下一次CPU调度。S睡眠(可中断阻塞)状态(sleeping)意味着进程在等待事件完成没错子进程就是该状态为什么呢都是循环打印和不打印有什么区别呢在上述操作系统中外设也有对应的数据结构所以在打印时cpu会切换其他进程(显示器)而且cpu的运行速度是非常快的硬件存储时是非常慢的(打印过程)所以我们在查看进程时总是只能看见子程序在休眠因为代码执行快结果出的慢。D磁盘休眠(不可中断阻塞、不可中断挂起)状态(Disk sleep)有时候也叫不可中断睡眠状态在这个状态的进程通常会等待IO的结束。ctrlc是不能终止的当操作系统中内存要满时会挂起一些进程如果解决不了就会杀死一些进程而有时候会杀死错某些重要的进程如果在这之前将那些被杀死的程序改成D状态就不会被杀死相当于免死金牌OS无法将他们杀死。3挂起状态挂起是进程的特殊挂起状态进程会被操作系统从内存换出到外存如磁盘完全不占用CPU和内存资源仅在外存保留进程映像如PCB等。T停止(可中断挂起)状态(stopped)可以通过发送特定信号给进程来停⽌T进程。这个被暂停的进程也可以通过发送特定信号让进程继续运行。这个信号是什么呢首先kill -9是杀死进程那他其他的编号对应什么功能呢SIGSTOP对应的就是停止SIGCONT对应的就是继续分别是19、18X死亡状态(dead)这个状态只是⼀个返回状态你不会在任务列表里看到这个状态。Z僵尸状态(zombie)这是一个特殊的状态当子进程退出时父进程没有读到子进程退出的返回码时就会产生僵尸进程。僵死进程会以终止状态保持在进程表中并且会⼀直在等待父进程读取退出状态代码。所以会一直占用内存会产生内存泄漏#include stdio.h #include sys/types.h #include unistd.h int main() { int ret fork(); // printf(%d, ret: %d\n, getpid(), ret); if (ret 0) { //while (1) //{ // printf(I am a child, pid: %d, ppid: %d\n, getpid(), getppid()); // sleep(1); //} printf(I am a child, pid: %d, ppid: %d\n, getpid(), getppid()); sleep(1); } else if (ret 0) { printf(I am a father, pid: %d, ppid: %d\n, getpid(), getppid()); while (1) { } } return 0; }那我们如何去回收退出的子进程我们需要用到wait()函数。它是系统函数这里笔者就不给大家做函数解析了就直接用了。但有一点要提就是在等待的时候父进程会进入阻塞状态等待子进程结束才可以继续运行。孤儿进程父进程先于子进程退出的话子进程就会形成孤儿进程那这时候子进程退出是由谁来回收会不会也形成僵尸进程答案是肯定不会它会被1号init/systemd进程领养所以init/systemd进程就会正常进行回收。前后台运行这有个小知识点进程状态后带了号的是前台运行没有的是后台运行./test 启动进程会直接进入后台运行。前台运行会占用终端你无法输入可以用ctrlc来终止后台运行不会占用终端你可以输入但进程会继续在终端打印ctrlc终止不了直接用kill -9 PID来杀死就行了。这次的内容就到这我们学习了进程中最常见的状态其中有于冯诺依曼层次有关的还有怎么回收子进程这些都为重要大家自己写的时候要多留意谢谢支持。

更多文章