Linux进程学习【进程状态】

简介: 进程 只有被OS管理好了,才能发挥它的全部功效,而系统中存在多个 进程,OS无法做到面面俱到,因此为了更好的管理进程,OS把 进程 分成了几种状态:阻塞、挂起、运行、休眠等等,至于每种状态的应用场景是什么、有什么用?本文将会带着大家认识的各种 进程 状态

✨个人主页: Yohifo

🎉所属专栏: Linux学习之旅

🎊每篇一句: 图片来源

🎃操作环境: CentOS 7.6 阿里云远程服务器


Perseverance is not a long race; it is many short races one after another.


毅力不是一场漫长的比赛;是许多短跑一个接一个。


31fc6e7823db569186bd9b5b417513d.png


📘前言


进程 只有被OS管理好了,才能发挥它的全部功效,而系统中存在多个 进程,OS无法做到面面俱到,因此为了更好的管理进程,OS把 进程 分成了几种状态:阻塞、挂起、运行、休眠等等,至于每种状态的应用场景是什么、有什么用?本文将会带着大家认识的各种 进程 状态


840b8669822cef9699439b1c72cbc52.png


📘正文


在谈 进程状态 之前,首先要回顾下之前的 进程 相关知识


OS管理的本质是先描述,再组织

OS并非直接管理 进程 ,而是管理 进程 的 PCB(task_struct)

PCB 中有着进程的各种信息,包括:PID、PPID、进程状态等

我们可以通过函数 getpid() 获取当前进程的 PID

进程 间存在父子关系,可以通过 fork() 主动创建 子进程

父子进程 相互独立,共享一份代码时,具有 写时拷贝 机制


📖阻塞


何为阻塞?

bd56921a40fe1bf8aa578c1ba4f0778.png

阻塞 就是 进程 因等待某种条件就绪,而导致的一种不推进状态

通俗来说,阻塞 就是 进程 卡住了,原因就是缺少资源

比如在我们日常生活中,常常发生堵车,原因就是道路资源不够用了,车辆这个 进程 就需要原地等待


那么进程需要什么资源呢?


比如 磁盘、网卡、显卡 等各种外设

假设你现在想在 steam 上下载游戏,当你点击下载按钮后提示磁盘空间不足,此时是无法运行 steam下载 这个进程的,因为此 进程 需要等待足够大的 磁盘资源

此时我们就称此 进程 为 阻塞 状态

5c1c26c92406ebda59f2316c4315c15.png

总结


进程阻塞就是不被调度

原因


进程的 task_struct 结构体需要在某种被 OS 管理的资源下排队


📖挂起


理解 进程阻塞 后,理解 进程挂起 就比较轻松了


挂起(阻塞挂起)


当 CPU 资源紧张时,将 进程 交换至 磁盘 中挂起,此时内存中只有 PCB

挂起可以看作一种特殊的阻塞状态


比如在我们生活中,一边走路一边玩手机很危险,所以此时我们会将玩手机这个 进程挂起 ,即把手机揣进兜里,然后 专心执行走路这个 进程

6938f58e40db707c525d6b5413c7e01.png


📖进程状态


进程 有各种运行状态,方便OS进行管理,在 Windows 中,进程 状态是这样的


而在我们 Linux 中,新建、就绪、运行都可以看作 运行 R 这一个状态,所以比较清晰


8f40147ee009e6cee5cdce54bb9aeed.png

而我们今天要学习的正是 Linux 中的 进程 状态


进程是何种状态,取决于此进程的PCB在哪里排队

4b395c82236d93afdd53b1f30db4f28.png

🖋️运行 R


首先来看看第一种状态 R

以我们以往的认知来说,一个程序在运行就表示该 进程 处于 运行 状态,那么事实真的如此吗?


先来看看下面这段代码:


#include<iostream>
using namespace std;
#include<unistd.h>
#include<sys/types.h>
int main()
{
  while(1)
  {
    cout << "I'm a process, my PID is:" << getpid() << endl;
    sleep(1);
  }
  return 0;
}


当前 Makefile 文件为


myProcess:test.cpp
  g++ -o myProcess test.cpp
.PHONY:catPI
catPI:
  ps ajx | head -1 && ps ajx | grep myProcess | grep -v grep 
.PHONY:clean
clean:
  rm -r myProcess


通过 make catPI 指令调用 Makefile 中提前设定好的指令,查看当前进程信息

4ede7eab86ee46f6acbecfcfb929602e.gif

0d6c6be7492dd0829e8103618043f26.png


可以看到当前的进程状态为 睡眠 S+

注: + 表示当前进程在前台运行中


进程 难道没有运行吗?


运行了,但我们 很难捕捉到

对于 CPU 来说,将这么简单的一句话输出到屏幕上是一件很小的事,可能几毫秒就完成了

而其他大多数时间,进程 都在外设等待队列中 排队

当我们将打印语句和睡眠语句屏蔽后,进程 不用在等待队列中 排队, CPU 就一直在处理死循环,此时可以观察到 运行 R 状态

3fef8e87e7edbf6b3abc52182cda282.png

此时进程 myProcess 就在运行中


注意: R 表示此时 进程 已经在 运行队列 中排队了,但 进程 不一定在 CPU 上运行


🖋️睡眠 S


睡眠 S 的本质就是 进程阻塞,表示此时进程因等待某种资源而暂停运行;睡眠 S 又称为可中断休眠,当 进程 等待时间过长时,我们可以手动将其关闭,应用卡死后强制关闭也是这个道理


4f2a571b66ed8dca4da0a888ec83e4b.png

还有一种方式终止进程:kill

70e774cec7b3614af294d0a454054c7.png

kill -9 PID 终止进程,当进程在后台运行时(状态不加 +),我们是无法通过 ctrl+c 终止的,但 kill 指令可以终止


🖋️休眠 D


还存在一种特殊睡眠状态 休眠 D,休眠 又被称为不可中断休眠,顾名思义,休眠 D 状态下的 进程 是无法终止的,kill 指令和 OS都无能为力,只能默默等待 进程阻塞 结束,拿到资源了,进程 才会停止 休眠 D 状态


终止 休眠 D 进程的一个方法就是切断电源,此时进程是结束了,但整个系统也结束了


倘若存在 休眠 D 进程长时间运行,那么此时就表示系统离宕机不远了


不可休眠状态比较少见,一般出现于IO阻塞


用途:


使操作系统无法杀死该 进程,预防误杀现象

🖋️暂停 T


我们还可以使 进程 进入 暂停 T 状态


kill -19 PID 暂停进程

kill -18 PID 恢复进程


7253bd470eaba46da7794e817f657ca.png

我们可以通过 kill -18 PID 使 进程 恢复运行,恢复后的 进程 在后台运行

ebebe7a92a3ad80b7f557c0e866f126.png

注意: 进程 在后台运行时,是无法通过 ctrl+c 指令终止的,只能通过 kill -9 PID 终止


在 gdb 中调试代码时,打断点实际上就是 使 进程 在指定行暂停运行,此时 进程 处于 追踪暂停状态 t4dd16a88a0a246d9dc18d24db9deaa9.png


🖋️死亡 X


当进程被终止后,就处于 死亡 X 状态


死亡状态是无法在任务列表中观察到的,死亡 X 状态只是一个返回状态


🖋️僵尸 Z


与死亡状态相对应的还有一个 僵尸 T 状态


通俗来说,僵尸状态 是给 父进程 准备的

当 子进程 被终止后,会先维持一个 僵尸 状态,方便 父进程 来读取到 子进程 的退出结果,然后再将 子进程 回收

单纯的在 bash 环境下终止 子进程,是观察不到 僵尸状态 的,因为 bash 会执行回收机制,将 僵尸 回收

我们可以利用 fork() 函数自己创建 父子进程 关系,观察到这一现象

#include<iostream>
using namespace std;
#include<unistd.h>
#include<sys/types.h>
int main()
{
  pid_t ret = fork();
  if(ret == 0)
  {
    while(1)
    {
      cout << "I'm son process, my PID: " << getpid() << " PPID: " << getppid() << endl;
      sleep(1);
    }
  }
  else if(ret > 0)
  {
    while(1)
    {
      cout << "I'm father process, my PID: " << getpid() << " PPID: " << getppid() << endl;
      sleep(1);
    }
  }
  else
  {
    while(1)
    {
      cout << "Make son process fail!" << endl;
      sleep(1);
    }
  }
  return 0;
}

cf22a56a60d1696d732453ce4d3e0ae.png

25d22b89878028d9c88fc364a520f2d.png


此时输入指令 kill -9 PID 即 kill -9 28315 终止 子进程

再次查看进程状态:

4ef75ca8b4a1e93ac5036c831734fb4.png

僵尸进程如果不被回收,会导致内存泄漏问题和标识符占用问题

关于 僵尸进程 的更多信息,将会在下篇文章中介绍


📖孤儿进程


孤儿进程是一种特殊的进程状态


通过程序创建 父子进程

通过指令终止 父进程,此时 子进程 会被OS领养

子进程 的 父进程 变为 1号进程

子进程 就变成了一个 孤儿进程

2b76a719ce603c3fbb3ff44324287aa.png

发出指令终止 父进程

c78f52ac0199b789b611513de7ce439.png

假设 子进程 不被 1号进程 领养


子进程 退出时就会无人回收,成为一只游离的僵尸

僵尸进程 有 内存泄漏 的风险

因此 子进程 会被OS领养

📘总结


以上就是关于进程学习【进程状态】的全部内容了,我们简单学习了 进程 的相关状态,知道了何为 阻塞、进程 为什么 阻塞 的缘由,同时还见识了 进程 的各种状态,为以后 进程 进一步学习和控制打下了基础


如果你觉得本文写的还不错的话,期待留下一个小小的赞👍,你的支持是我分享的最大动力!


如果本文有不足或错误的地方,随时欢迎指出,我会在第一时间改正



目录
相关文章
|
9天前
|
监控 Linux 应用服务中间件
探索Linux中的`ps`命令:进程监控与分析的利器
探索Linux中的`ps`命令:进程监控与分析的利器
|
3天前
|
Ubuntu Linux vr&ar
IM跨平台技术学习(十二):万字长文详解QQ Linux端实时音视频背后的跨平台实践
本文详细记录了新版QQ音视频通话在 Linux 平台适配开发过程中的技术方案与实现细节,希望能帮助大家理解在 Linux 平台从 0 到 1 实现音视频通话能力的过程。
19 2
|
3天前
|
小程序 Linux
【编程小实验】利用Linux fork()与文件I/O:父进程与子进程协同实现高效cp命令(前半文件与后半文件并行复制)
这个小程序是在文件IO的基础上去结合父子进程的一个使用,利用父子进程相互独立的特点实现对数据不同的操作
|
3天前
|
SQL 自然语言处理 网络协议
【Linux开发实战指南】基于TCP、进程数据结构与SQL数据库:构建在线云词典系统(含注册、登录、查询、历史记录管理功能及源码分享)
TCP(Transmission Control Protocol)连接是互联网上最常用的一种面向连接、可靠的、基于字节流的传输层通信协议。建立TCP连接需要经过著名的“三次握手”过程: 1. SYN(同步序列编号):客户端发送一个SYN包给服务器,并进入SYN_SEND状态,等待服务器确认。 2. SYN-ACK:服务器收到SYN包后,回应一个SYN-ACK(SYN+ACKnowledgment)包,告诉客户端其接收到了请求,并同意建立连接,此时服务器进入SYN_RECV状态。 3. ACK(确认字符):客户端收到服务器的SYN-ACK包后,发送一个ACK包给服务器,确认收到了服务器的确
|
6天前
|
Linux 数据处理 调度
深入探索Linux的renice命令:优化进程优先级
`renice`命令在Linux中用于调整运行进程的优先级,范围-20(最高)至19(最低)。它可以实时改变进程的优先级,无需重启,支持按PID、进程组或用户批量修改。例如,`renice -n 10 -p 1234`将PID为1234的进程优先级设为10。使用时要注意不要滥用高优先级,避免频繁修改,了解系统负载,并记录变更,通常需root权限。
|
7天前
|
缓存 Linux Shell
Linux进程控制
本文介绍了进程创建、等待、终止的方法,以及如何进行程序间进程替换。
9 0
Linux进程控制
|
9天前
|
Web App开发 运维 监控
深入探索Linux命令pwdx:揭秘进程工作目录的秘密
`pwdx`命令在Linux中用于显示指定进程的工作目录,基于`/proc`文件系统获取实时信息。简单易用,如`pwdx 1234`显示PID为1234的进程目录。结合`ps`和`pgrep`等命令可扩展使用,如查看所有进程或特定进程(如Firefox)的目录。使用时注意权限、进程ID的有效性和与其他命令的配合。查阅`man pwdx`获取更多帮助。
|
9天前
|
存储 缓存 NoSQL
Redis系列学习文章分享---第十三篇(Redis多级缓存--JVM进程缓存+Lua语法)
Redis系列学习文章分享---第十三篇(Redis多级缓存--JVM进程缓存+Lua语法)
21 1
|
6天前
|
缓存 Linux 调度
【linux】进程控制——进程创建,进程退出,进程等待
【linux】进程控制——进程创建,进程退出,进程等待
|
6天前
|
Linux
【Linux】进程地址空间
【Linux】进程地址空间