目录

1.情景引入

2.操作系统学科对进程状态的分类

运行状态

基于时间片的轮转调度算法

阻塞状态

等待IO设备的例子

等待其他进程中需要获取的数据

进程唤醒

挂起状态(全称为阻塞挂起状态)

简单谈谈虚拟内存管理

就绪状态

笔面试题

3.Linux对进程状态的分类

R和S状态 

前台运行

结论

D状态

实验:模拟高IO访问的情况

结论

T和t状态

T状态

t状态

结论

X状态

4.交换分区的简单了解

两个命令查看交换分区


1.情景引入

C语言代码中的scanf函数会等待用户的输入,那么此时的进程处于闲置的状态

2.操作系统学科对进程状态的分类

例如《 计算机操作系统 慕课版 》第65页:

又如 《 操作系统导论 中译版 》第22页:

又如《 现代操作系统原理与实现》第77页

会发现不同的操作系统书籍对进程的状态的描述都不太一样,但大致分4类:

运行状态、阻塞状态、挂起状态和就绪状态

运行状态

运行状态: 处于运行队列中的进程所处的状态,即进程已经准备好了,可以随时被调度

现认为计算机中只有一个CPU,进程需要占用CPU资源,操而作系统中有很多进程,那么这些进程相互之间一定存在竞争,可以通过调度器保证CPU资源均衡使用,而老师,调度器的其中一个任务是将进程链接到运行队列中,CPU要运行进程时直接在运行队列中队头进程

例如底层为双向链表结构的运行队列:

struct running_queue
{struct running_queue* head;struct running_queue* tail;
}

(注意:是进程的PCB在运行队列中排队)

基于时间片的轮转调度算法

思考一个问题:一个进程只要把自己放到CPU上开始运行了,是不是一直要执行完毕才能把自己放下来?

答:如果是死循环呢?如果按上面这样做,死循环进程会一直占用着CPU的资源,而其他进程得不到执行,会导致操作系统崩溃

那么需要保证进程公平被调度,引入基于时间片的轮转算法(调度算法中的一种)

每个进程都有一个叫做时间片的东西,是分时操作系统分配给每个正在运行的进程微观上的一段CPU时间,通常很短

当一个进程的时间片到了,CPU会暂停执行该进程,转而执行下一个进程,这叫进程切换.暂停执行的进程如果没有执行完,会继续排队

进程切换: 大量的把进程从CPU上放上去,再拿下来的动作 

阻塞状态

阻塞状态:进程无法继续执行,处于正在等待某个资源就绪的状态

等待的事件可能为:

1. 等待特定设备,例如IO设备

2. 等待操作系统某些服务,例如内核返回数据

3. 等待其他进程中需要获取的数据

4. 等待子进程退出

等待IO设备的例子

假设进程A要读取硬件数据,例如键盘

先想想操作系统是什么管理硬件的?

答:先描述再组织.描述硬件可以用结构体对象,而组织硬件就是将硬件对应的结构体连接起来

当没有从键盘键入数据时,进程A在等待设备,不能放到运行队列中,要放到等待队列(每个硬件的结构体中有等待队列)中

由于处于阻塞状态的进程的PCB在等待队列中,不在运行队列中,则进程不占用CPU资源,因此在用户看来,进程"卡"住了

等待其他进程中需要获取的数据

之前在OS8.【Linux】基本权限(上)文章提到过,fifo可用于终端之间的通信,现在演示阻塞状态

先创建fifo文件:

mkfifo myfifo

再用XShell复制一份选项卡:

写入字符串时,如果另一个终端没有接收会导致进程阻塞:

如果另一个终端接收了:

原理:

命名管道是一端写入另一端读取的通信机制,在写入命名管道的时如果没有任何进程在读取,它就会阻塞,直到有一个读取方连接上来

进程唤醒

定义: 从阻塞状态到运行状态

挂起状态(全称为阻塞挂起状态)

1.当操作系统的内存资源严重不足时,为了保证操作系统自己运行正常,需要节省内存资源

2.如果某个进程在等待,它无事可做,那么操作系统就保留该进程的PCB,但代码和数据放到外设(磁盘)中,这叫调离内存,也称为换出

了解: 如何确定进程在内存中还是在外设中,可以看段描述符

 

(摘自《x86汇编语言:从实模式到保护模式 第二版》)

简单谈谈虚拟内存管理

当程序超出了物理内存的大小时,或者操作系统无法分配这么大的物理内存空间时,操作系统要使用虚拟内存管理

下面摘自《x86汇编语言:从实模式到保护模式 第二版》

3.挂起状态:处于调离内存状态的进程

4.当条件允许时,操作系统会将该进程调回内存,也称为换入.如果这个进程所有资源已经就绪了,那么只剩调度了,就会按操作系统设计的调度算法来调度进程,可以认为该进程处于运行状态

5.挂起状态全称为阻塞挂起状态: 只要是等待资源的进程都可以说阻塞

就绪状态

就绪状态: 处于已准备好执行的状态的进程 即满足调度的条件了,但是CPU没调度他(预备执行)

*注:就绪状态和运行状态不用区分那么仔细,因为因为CPU调度是很快的,一般只要进程在运行队列里面,就可以认为是运行状态

笔面试题

得物二面:阻塞态和就绪态会占用CPU吗?

答: 1.阻塞态从大的角度说是不影响的,因为阻塞是阻塞在IO或者其他上了,自然不被CPU调度,不占用CPU 2.就绪态从大的角度说是等待被调度,而等待被调度自然还没有占用CPU

科大讯飞笔试:进程的状态? 什么情况触发就绪,什么情况触发阻塞?

答:见上方总结

快手一面;就绪态和运行态的区别?

答:见上方总结

3.Linux对进程状态的分类

看看Linux内核源代码对进程状态的定义:

fs/proc/array.c下:https://github.com/torvalds/linux/blob/master/fs/proc/array.c

/** The task state array is a strange "bitmap" of* reasons to sleep. Thus "running" is zero, and* you can test for combinations of others with* simple bit tests.*/
static const char * const task_state_array[] = {/* states in TASK_REPORT: */"R (running)",		/* 0x00 */"S (sleeping)",		/* 0x01 */"D (disk sleep)",	/* 0x02 */"T (stopped)",		/* 0x04 */"t (tracing stop)",	/* 0x08 */"X (dead)",		/* 0x10 */"Z (zombie)",		/* 0x20 */"P (parked)",		/* 0x40 *//* states beyond TASK_REPORT: */"I (idle)",		/* 0x80 */
};

以这个测试代码为例说明R和S状态:

#include <stdio.h>
#include <unistd.h>
int main()
{while(1){printf("The process is runnning...\n");}return 0;
}

R和S状态 

运行上方代码,再开一个终端捕获该进程的运行状态:

 发现多次捕获发现a.out进程都是"S+"状态.不是R状态

答:这是一个概率问题,R状态相比S状态存在的时间极短,此进程绝大部分时间在等待IO设备(这里是显示器),即处于睡眠状态S (sleeping) 

又比如bash命令行解释器,其大部分时间在等待用户的输入,处于S状态

修改以上代码:

#include <stdio.h>
#include <unistd.h>
int main()
{while(1);return 0;
}

捕获结果:

执行while(1);是不需要等待显示器资源的,因此进程处于R状态,一直在执行

前台运行

注:R+和S+的+指的是前台运行,即通过终端展示前台进程的信息

进一步解释:进程运行是在内存中通过操作系统的调度算法+ CPU来完成的.进程在运行时,开发者一定是想知道进程的一些调试信息的,所以有的进程会看调用printf、scanf等函数,而这些函数都是与外设来交互的,那么使用printf时,就是向显示器文件输出的,即通过终端呈现出来,对于scanf,输入时,用户也需要要知道自己输入了什么,需要在显示器文件中显示的,也是通过终端来完成的.因此终端主要是展示前台进程的信息的
如果是后台进程,它们的debug信息不可以向终端输出,只能向文件输出,也就是日志

1.在bash中执行命令时默认是前台运行

2.和前台运行对应的是后台运行,在命令后加&可以让进程在后台运行

例如运行刚刚的程序:

终端返回了进程的PID : 11628

可以用kill来杀死进程,Ctrl+C是没有用的

结论

R (running)状态相当于操作系统的运行状态,而S (sleeping)状态相当于操作系统的阻塞状态

D状态

D状态:处于等待某些不可中断的资源状态的进程

例如进程正在向磁盘中写入数据时,进程需要等待写入磁盘的结果

进一步解释:进程A正在向磁盘中写入数据时,如果操作系统的内存资源严重不足,如果操作系统杀死正在待磁盘写入结果的进程A,那么设想一下: 如果磁盘写入失败,那么磁盘无法报告给进程A,有丢失数据的风险,这会出问题

解决方法:让进程A在等待磁盘写入完毕期间,该进程不能被操作系统杀掉,则进程A处于D状态

对比S状态和D状态,S状态是浅度睡眠,而D状态是深度睡眠,而且深度睡眠和浅度睡眠都是等待某资源就绪,因此都属于阻塞状态

浅度睡眠(S状态又称为Interruptible Sleep n.可中断睡眠)可以被唤醒,而深度睡眠是不能被唤醒的,称为Uninterruptible Sleep n.不可中断睡眠,处于D状态的进程是操作系统(注意主体!!)是无法使用kill命令杀死的,而且该进程不会响应任何请求

以下摘自redhat processstates

Uninterruptible Sleep State
An Uninterruptible sleep state is one that won't handle a signal right away. It will wake only as a result of a waited-upon resource becoming available or after a time-out occurs during that wait (if the time-out is specified when the process is put to sleep).
The Uninterruptible state is mostly used by device drivers waiting for disk or network I/O. When the process is sleeping uninterruptibly, signals accumulated during the sleep are noticed when the process returns from the system call or trap. In Linux systems. the command ps -l uses the letter D in the state field (S) to indicate that the process is in an Uninterruptible sleep state. In that case, the process state flag is set as
follows:

                                        p->state = TASK_UNINTERRUPTABLE
LEARN MORE: Read more about D states in the Red Hat Knowledgebase:
https://access.redhat.com/knowledge/solutions/59989/

实验:模拟高IO访问的情况

模拟处于D状态的进程,例如生成一个较大的文件:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <cstdlib>
#include <string.h>
#include <random>
#include <ctime>
#include <climits>
#define BUFFER_SIZE 1024 * 1024 * 5//5MB缓冲区
int main() 
{// 分配缓冲区unsigned long long* buffer = (unsigned long long*)malloc(BUFFER_SIZE);if (buffer == NULL) {perror("malloc fail");return -1;}std::uniform_int_distribution<unsigned long long> distribution(0, ULLONG_MAX);std::default_random_engine generator;// 打开文件printf("create random numbers.bin......\n");FILE* fptr = fopen("random numbers.bin", "wb");if (fptr == NULL){perror("Fail to open file!\n");free(buffer);return -1;}printf("writing data......\n");srand((unsigned int)time(NULL));int times =2048;while (times--){//先填满缓冲区unsigned long long buf_index = 0;while (buf_index < BUFFER_SIZE/8){unsigned long long random = distribution(generator);buffer[buf_index] = random;buf_index++;}printf("write buffer%d,bin file's size:%dMB\n", 2048 - times, (2048 - times)*5);fwrite(buffer, sizeof(unsigned long long), BUFFER_SIZE / sizeof(unsigned long long), fptr);}printf("done!\n");printf("free buffer......\n");free(buffer);printf("close file......\n");fclose(fptr);printf("press any key to quit\n");getchar();return 0;
}

运行结果:

结论

1.D状态本身是操作系统正常处理IO的表现,一般处于D状态的进程持续时间较短

2.但如果大量进程持续处于D状态,会占用大量资源,操作系统会负载,容易产生故障

拓展阅读可以看看闪客大佬这篇文章:闪客 什么叫进程被 D 了

T和t状态

T和t状态的区别暂时不讲,当然认为都是暂停状态

T状态

例如执行以下代码

#include <stdio.h>
int main()
{while(1);return 0;
}

使用kill -l命令查看所有能发送的信号

向进程发送19号信号SIGSTOP:

kill -19 92159

再次使用ps命令查看:进程被暂停

向进程发送18号信号可继续执行:

t状态

int main()
{return 0;
}

使用gdb(有关gdb的使用参见OS15.【Linux】gdb调试器的简单使用文章)在return 0处下断点,

之后使用ps命令查看:发现进程a.out处于t状态,因为gdb控制了a.out进程

结论

处于T或t状态的进程可能被其他进程控制

X状态

X状态(dead):进程处于终止状态

注意:X状态只是一个返回状态,任务列表里是看不到这个状态的

4.交换分区的简单了解

在linux中,将进程换出到磁盘,实际上换出到交换分区(swap分区)

可以在Linux mint桌面版的系统监视器中看到:

两个命令查看交换分区

在Linux mint桌面版下演示:

swapon --show

free -h

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/915480.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/915480.shtml
英文地址,请注明出处:http://en.pswp.cn/news/915480.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何优雅地修改项目的 Android 版本(API 级别)

引言 在 Android 开发的日常迭代中&#xff0c;我们经常需要升级或降级项目的 minSdkVersion、targetSdkVersion 与 compileSdkVersion。升级可以解锁新特性和性能优化&#xff1b;降级则可能为了兼容旧机型或快速验证问题。本文将手把手演示在 Android Studio 里修改 Android …

GNU Radio多类信号多种参数数据集生成技巧

参考我的这篇博客&#xff0c;我想自制一个多信号数据集&#xff1a; 【多雷达信号硬件模拟】 3台USRP1台VSG信号发生器模拟多雷达信号&#xff0c;1台USRP产生高斯噪声模拟更多信道环境&#xff0c;1台USRP采集信号 需要在多个波段对四种信号进行参数设置&#xff0c;带宽有…

Ansible + Shell 服务器巡检脚本

脚本概述这是一个用于服务器日常巡检的 Shell 脚本&#xff0c;主要功能包括&#xff1a;检查多台主机的网络连通性 监控CPU、内存和磁盘使用率 生成详细的巡检报告 通过企业微信发送告警通知核心技术点1. 主机批量管理使用Ansible工具远程执行命令和脚本 通过主机…

Linux-rpm和yum

一、RPMRPM&#xff08;Red Hat Package Manager&#xff09;是一个用于管理 Red Hat 系列 Linux 发行版&#xff08;如 RHEL、CentOS、Fedora&#xff09;软件包的工具。RPM 允许用户以统一的格式来安装、卸载、升级和查询软件包。它是 .rpm 文件的主要工具&#xff0c;后缀名…

手推OpenGL相机的正交投影矩阵和透视投影矩阵(附源码)

概述计算OpenGL的正交投影矩阵和透视投影矩阵是有现成函数的。自己手推不是为了重复造轮子。手推一遍&#xff0c;可以极大的加强对这两个矩阵的理解。同时也可以满足一下自己求知欲。正交投影矩阵手推正交投影矩阵源码 WGMatrix4x4 WGMatrix4x4::BuildOrtho(double l, double …

【跨国数仓迁移最佳实践2】MaxCompute SQL执行引擎对复杂类型处理全面重构,保障客户从BigQuery平滑迁移

本系列文章将围绕东南亚头部科技集团的真实迁移历程展开&#xff0c;逐步拆解 BigQuery 迁移至 MaxCompute 过程中的关键挑战与技术创新。本篇为第二篇&#xff0c;跨国数仓迁移背后 MaxCompute 的统一存储格式创新。 注&#xff1a;客户背景为东南亚头部科技集团&#xff0c;…

react(基础篇)

React由Meta公司研发&#xff0c;用于构建Web和原生交互界面的库。 React 官方中文文档 查看JSX &#xff08;一&#xff09;React组件 用户界面的一部分&#xff0c;通俗的来讲&#xff0c;最小的元素组成的单元&#xff0c;可以实现部分逻辑与功能 房子的门就可以看成一个…

数据结构-哈希表(一)哈希函数、哈希表介绍、优缺点

哈希表 哈希函数哈希表使用了哈希函数来完成key到地址的快速映射&#xff0c;所以在了解哈希表之前&#xff0c;需要先明白哈希函数的概念和特点。 哈希函数的定义 哈希函数 哈希函数是一种将任意长度输入的数据&#xff0c;转换成固定长度输出的算法哈希函数H可以表示为yH(x) …

Shader开发(一)什么是渲染

前言在现代游戏开发和计算机图形学领域&#xff0c;渲染技术是连接虚拟世界与视觉呈现的关键桥梁。无论你是刚接触图形编程的新手&#xff0c;还是希望深入理解渲染原理的开发者&#xff0c;掌握渲染的核心概念都是必不可少的第一步。什么是渲染&#xff1f;渲染&#xff08;Re…

策略模式+工厂模式(案例实践易懂版)

最近,可以说这2025年度,自己更文的次数都大大减少,主要最近大环境不景气,自己职业也受到波及,学习的东西也是因为AI而变得更多, 没办法,你不学,总有人会学,关于AI的我也准备出个专辑,相信绝对帮助到大家 额,好像说多了,言归正传,我们看一下今天的主题:策略模式工厂模式 本文主要…

【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - snowNLP库实现中文情感分析

大家好&#xff0c;我是java1234_小锋老师&#xff0c;最近写了一套【NLP舆情分析】基于python微博舆情分析可视化系统(flaskpandasecharts)视频教程&#xff0c;持续更新中&#xff0c;计划月底更新完&#xff0c;感谢支持。今天讲解snowNLP库实现中文情感分析 视频在线地址&…

大根堆,小根堆,双指针

码蹄集OJ-大约 #include<bits/stdc.h> using namespace std; priority_queue<int>max2,maxDel; priority_queue<int,vector<int>,std::greater<int>>min2,minDel; const int N1e51; int n,result0,a[N]; int main( ) {cin>>n;for(int i1…

RS485和Modbus

UART协议中&#xff0c;空闲状态为高电平&#xff0c;也就是1,R25和R27&#xff0c;485收发器特性MAX485 (美信)SSP485 (国产替代)AZRS3080 (安格)供电电压5V5V3.3V ~ 5.5V静态电流300μA (接收模式)120μA (接收模式)150μA (接收模式)传输速率2.5Mbps10Mbps20Mbps总线负载能力…

【Android】交叉编译faiss库 | 问题解决

目录 一 解决 FAISS 交叉编译到 Android 时的 BLAS/MKL 依赖问题 二 交叉编译faiss ■禁用 BLAS并交叉编译faiss ■使用 OpenBLAS 的 Android 移植版本并交叉编译faiss 三 报错处理 ■报错 ■SWIG 一 解决 FAISS 交叉编译到 Android 时的 BLAS/MKL 依赖问题

《使用 IDEA 部署 Docker 应用指南》

使用 IDEA 部署 Docker 应用的详细步骤 一、创建 Dockerfile 配置文件 在项目根目录下创建Dockerfile文件&#xff0c;配置内容如下&#xff1a; # 使用官方的OpenJDK镜像作为基础镜像 FROM openjdk:17-jdk-slim# 设置维护者信息(可选) LABEL maintainer"三木豪"# 设…

【Docker#3】Window 和 Linux 上 docker安装 相关知识

前置了解&#xff1a; X86 高并发&#xff1a;基于 x86 架构的处理器&#xff0c;在高负载下处理大量并发请求的能力。ARM &#xff1a;使用 ARM 架构处理器的移动设备&#xff0c;具有低功耗和高性能的特点。 操作系统&#xff1a; CentOS&#xff1a;基于 Red Hat Enterprise…

一次 POI 版本升级踩坑记录

前言 结论先行。 开发过程中由于可能涉及到二次开发&#xff0c;若原系统开发时间久远&#xff0c;没有达成一致规范设计&#xff0c;导致风格各异&#xff0c;确实满足当时开发场景&#xff0c;但增大了后续的更新的难度&#xff0c;容易出现俄罗斯套娃现象&#xff0c;新的更…

硬件设计学习DAY13——电源缓冲电路设计全解

每日更新教程&#xff0c;评论区答疑解惑&#xff0c;小白也能变大神&#xff01;" 目录 一.缓冲电路介绍 1.1缓冲电路的作用 1.2寄生参数的来源 1.3缓冲电路的类型 1.4常见缓冲电路设计 1.5设计原则 二.吸收与缓冲 2.1吸收与缓冲的核心作用 2.2电压尖峰与吸收措…

鸿蒙搜狐新闻如何在Native调用ArkTS方法

01前言鸿蒙作为一款新兴的智能操作系统&#xff0c;现在适配鸿蒙系统的应用越来越多&#xff0c;同时会面临三端兼容问题&#xff0c;如同一产品功能&#xff0c;需要维护iOS、Android、鸿蒙三端代码。拿文件上传、下载功能场景举例&#xff0c;同时要适配iOS、Android、鸿蒙三…

Java行为型模式---中介者模式

中介者模式基础概念中介者模式&#xff08;Mediator Pattern&#xff09;是一种行为型设计模式&#xff0c;其核心思想是通过一个中介对象来封装一系列对象之间的交互&#xff0c;使各对象不需要显式地相互引用&#xff0c;从而降低耦合度&#xff0c;并可以独立地改变它们之间…