当前位置: 首页 > news >正文

Linux 下进程的状态

操作系统中常见进程状态

在操作系统中有六种常见进程状态:

  1. 新建状态: 进程正在被创建. 此时操作系统会为进程分配资源, 如: 内存空间等, 进行初始化
  2. 就绪状态: 进程已经准备好运行了, 只需要等待被调度, 获取 CPU 资源就可以执行了, 操作系统中可能同时存在多个进程处于就绪状态, 都在排队等待获取 CPU 资源
  3. 运行状态: 进程获得了 CPU 资源, 正在执行指令
  4. 阻塞状态: 进程因为需要等待某个条件而进行暂停执行
  5. 终止状态: 进程已经完成了任务或者因为一些错误结束了运行, 操作系统会回收进程占用的资源.
  6. 挂起状态: 挂起是一种特殊操作, 当系统内存资源紧张时, 一些暂时没有运行的进程会被暂时交换到外存中挂起.

运行状态

CPU 会维护一个运行队列.
CPU 会从这个队列中寻找数据来进行处理.

当一个进程被放在了运行队列中, 那么这个进程的状态就是运行状态.
无论这个基础是否正在被处理.

阻塞状态

进程因为需要等待某个条件而进行暂停执行

进程在运行过程中或多或少都会去访问一些操作系统的资源: 如硬盘里的数据, 网卡接受的数据 ...

最常见的: 我们在学习 C 或 C++ 时, 都写过从键盘上获取两个数据, 然后打印出这两个数据之和.
当我们这个程序运行起来之后, 就会在控制台中要我们输入数据, 如果我们一直不输入数据, 那么这个程序就不会向后执行. 这就是一种阻塞状态, 进程在一直在等待键盘的资源.

那么操作系统是怎么知道, 哪个进程需要键盘的数据的呢?

我们之前了解到: 操作系统是管理软硬件资源的, 并且是通过软硬件的信息来了解软硬件对应的状态, 从而管理. 

键盘也是一个硬件资源, 所以操作系统也会收集键盘的信息, 存放在一个 struct 结构体中.

像键盘, 硬盘这样的设备的 结构体中, 都会维护一个等待队列

需要这个设备资源的进程都会被链入这个队列中,

这样当资源来临时, 就可以将资源给到对应的进程

 

那么进程状态从 运行状态 到 阻塞状态, 都经历了什么:
将进程的 PCB 从运行队列移动到设备的等待队列, 将状态修改为阻塞状态. 自此状态的修改完成.

进程状态变化本质: 

  1. 更改进程 PCB 中的 status 字段
  2. 将进程 PCB 链入到等待队列中

挂起状态

挂起又分为:

  • 就绪挂起
  • 阻塞挂起

这两种状态之前的区别就是: 进程在挂起之前的状态.

当相同的内存严重不足的时候: 
就绪状态 和 阻塞状态的 进程此时因为资源没有就绪, 所以都还没有调度.

与其放在内存中继续占用内存, 不如先将这些进程的代码和数据弄到硬盘中,

为操作系统腾出一部分空间.

在硬盘中, 这部分用来存储挂起进程代码和数据的空间, 称为 swap分区.
swap分区通常很小, 这个部分专门用与这种情况.

问题: 频繁的和硬盘这种外设交互, 那么操作系统的效率不就变得很低? (相较于 CPU 访问内存, 访问硬盘这样的外设, 速度是非常慢的)

此时的操作系统正处于内存严重不足的情况, 如果再不腾出一部分空间, 可能下一秒就会直接宕机了.

此时, 操作系统更关心的是能否存活下去, 而不是效率, 如果操作系统直接宕机, 那么所有的进程都会直接结束, 哪还谈什么效率.

以上说的是通用的状态, 在 Linux 中进程的状态又有些不同.

 Linux中六种常见状态

  1. R 运行状态 (running)
  2. S 睡眠状态 (sleeping), 也称为可中断睡眠状态. 意味着进程在等待事件的完成
  3. D 磁盘休眠状态 (Disk sleep), 也可称为不可中断睡眠状态.
  4. T 停止状态 (stopped) 通过发送 SIGSTOP 信号给进程来停止 (T) 进程, 这个被暂停的进程可以通过接收 SIGCONT 信号, 让进程运行起来
  5. X 死亡状态 (dead): 表示一个进程已经完成其执行并即将被销毁. 这个状态只是一个返回状态,意味着进程已经结束其生命周期,但还没有被完全清除出系统. 这个状态下的进程不会在任务列表中出现. 而且这个状态非常短暂, 几乎不可能通过 ps 命令捕捉到.
  6. z 僵尸状态: 僵尸状态(Zombie State)是一种特殊的进程状态,它表示一个进程已经完成执行,但其父进程尚未回收其终止状态

 R 和 S状态

我们运行下面这段程序

#include <iostream>
#include <unistd.h>
int main()
{while(1){std::cout << "hello world" << std::endl;}return 0;
}

 使用 ps命令观察 ./a.out 这个进程.

 S+: 中的 + 号和前后台进程有关. 这个在文章后面来讲解.

我们会发现: 这个正在运行的进程没有处于 R 状态, 而是处于 S 状态. 为什么?

上面说过, 访问外设的速度非常慢, printf 会将内容打印到屏幕上,

屏幕就是一种外设, 与屏幕交互的速度很慢, 程序的大部分时间内,

都处于 阻塞状态, 在等待外设将内容显示到屏幕上.

真正处于运行的事件很少.

当然, 我们只需要将 cout 语句去掉, 一直循环, 那么就能观察到, 程序一直处于 R 状态

S 和 D状态

S 和 D 都是睡眠状态, 这两个睡眠状态有什么差别?
S: 可以被比作浅度睡眠
D: 可以被比作深度睡眠

当我们从 QQ 上下载一个文件时, 这个文件是需要被拷贝到硬盘中的

如果这个文件非常的大, 而此时操作系统的内存又不足了, 需要杀死一些进程,

腾出一些空间, 如果此时 QQ 就被杀死了, 那么文件的下载也就失败了,

这些数据可能是非常重要的, 而操作系统杀死了进程, 导致我的文件丢失了,

这是很麻烦的事情.

所以, 操作系统就提供了一个 D 状态, 当进程处于 D 状态时, 操作系统就不会杀死这个进程.
因为 D 代表此时进程正在和磁盘交互, 为了不如数据丢失, 不要杀掉这个进程.

结论: 

S (sleeping): 浅度睡眠, 可以被终止

D (disk sleep): 深度睡眠, 防止像硬盘写入数据时被杀掉而专门创立的状态

 

Z 僵尸状态

僵尸状态的出现和父子进程有关.

僵尸状态: 

僵尸状态是一种特殊的进程状态, 它表示一个进程已经完成执行, 但其父进程尚未回收其终止状态.

我们知道创建子进程, 是为了去完成任务, 那么这个任务是否完成, 完成的结果如何等信息, 都应该要告诉父进程. 

当子进程结束后, 而父进程没有没有接收子进程返回的信息, 那么子进程就不会被操作系统回收, 这时子进程就加入了僵尸状态.

前台/后台进程

在上面观察进程的 R / S 状态时, 我们可以看到进程的状态是 R+ / S+.
这个 "+" 是什么意思?

这个 "+" 代表这个进程是在前台运行的.
那什么叫前台进程, 什么叫后台进程?

前台进程: 可以在终端直接交互
后台进程: 不会接收终端的输入, 要结束后台进程通常使用 kill 命令.

代码:

#include <iostream>
#include <unistd.h>
int main()
{while(1){sleep(1);std::cout << "hello world" << std::endl;}return 0;
}

前台进程: 运行时无法使用bash外壳的指令并且可以被CTRL C强制终止掉

可以看到, 当进程在前台运行时, 我向终端输入 ls 命令, 并没有打印出当前目录下的文件.
此时我们只能和这个前台进程进行交互, 无法向命令行解释器发送指令.

后台进程: 运行时可输入指令,不能被CTRL C掉, 只能使用kill指令来杀掉进程.

在命令后面加上一个 &

./a.out &

可以看到, 我输入 ls 指令依然可以查询当前目录下的文件. Ctrl C 也无法终止这个进程

http://www.lryc.cn/news/493067.html

相关文章:

  • 【计算机网络】核心部分复习
  • Spring Boot开发实战:从入门到构建高效应用
  • pyshark安装使用,ubuntu:20.04
  • 基本功能实现
  • 《那个让服务器“跳舞”的bug》
  • Python 网络爬虫进阶:动态网页爬取与反爬机制应对
  • 创建可直接用 root 用户 ssh 登陆的 Docker 镜像
  • wordpress 中添加图片放大功能
  • 数据结构 (7)线性表的链式存储
  • 库的操作.
  • Vue进阶之Vue CLI服务—@vue/cli-service Vuex
  • 导入100道注会cpa题的方法,导入试题,自己刷题
  • 数据库操作、锁特性
  • 学习笔记039——SpringBoot整合Redis
  • (笔记)简单了解ZYNQ
  • 大众点评小程序mtgsig1.2算法
  • 七牛云AIGC内容安全方案助力企业合规创新
  • .net的winfrom程序 窗体透明打开窗体时出现在屏幕右上角
  • 基于YOLOv8深度学习的智慧课堂教师上课行为检测系统研究与实现(PyQt5界面+数据集+训练代码)
  • 使用 Tkinter 创建一个简单的 GUI 应用程序来合并视频和音频文件
  • 【C++笔记】模板进阶
  • Soul App创始人张璐团队亮相GITEX GLOBAL 2024,展示多模态AI的交互创新
  • ffmpeg.wasm 在浏览器运行ffmpeg操作视频
  • 用Python爬虫“偷窥”1688商品详情:一场数据的奇妙冒险
  • CentOS上如何离线批量自动化部署zabbix 7.0版本客户端
  • 【开源项目】ChinaAddressCrawler 中国行政区划数据(1980-2023年)采集及转换(Java版),含SQL格式及JSON格式
  • React中事件处理和合成事件:理解与使用
  • Local Changes不展示,DevEco Studio的git窗口中没有Local Changes
  • 大数据笔记
  • 【Linux网络编程】TCP套接字