进程(下)【Linux操作系统】
文章目录
- 进程的状态
- R状态:
- S状态:
- D状态:
- T状态
- t状态
- Z状态:
- 孤儿进程
- X状态:
- 进程的优先级
- 如果我们要修改一个进程的优先级
- 重置进程优先级
- 进程切换
- 进程的调度
进程的状态
在内核中,进程状态的表示,就是进程PCB中的一个int类型的成员变量,状态不同就存储着不同的数字
R状态:
就是运行状态
S状态:
就是普通的阻塞状态,进程处于浅睡眠
处于S状态的进程可以被操作系统杀死
D状态:
特殊的阻塞状态,进程处于深度睡眠
处于D状态的进程不可以被操作系统杀死
为什么需要 D 状态?
不可中断的 I/O 操作
当进程执行某些必须完成的底层操作(如磁盘写入、网络数据包接收或与硬件设备的交互)时,会进入 D 状态。这些操作通常由内核发起,进程必须等待其完成。
不能被信号(如 kill -9)中断。若强行中断,可能导致数据损坏或硬件状态不一致。
例
进程A的任务是向磁盘中写入银行的100万条交易数据
因为数据量较大,而且磁盘速度慢,所以会花费一些时间
所以A会在磁盘的等待队列中等待磁盘写完,获取磁盘进行写入的结果(即写入成功还是失败)
此时如果操作系统因为一些原因(内存不足或者用户使用指令杀进程A等)
把进程A杀死了
如果刚好磁盘也写入失败了,就会告知进程A:写入失败,询问是否重新写入
但是此时进A已经没了,自然就没人给磁盘应答,此时磁盘就可能会丢弃这些数据,就可能导致数据丢失
所以为了保护重要数据,正在与硬件交互重要数据的进程就不能被杀死
也就有了状态D
T状态
暂停状态
进入暂停状态的两种情况:
①进程做了非法但是不致命的操作
操作系统就会暂停进程,并把情况汇报给用户,让用户决定
②用户操作,让进程进入暂停状态(比如:双击屏幕暂停视频的播放)
t状态
可追踪的暂停状态
例
使用gdb调试器,调试可执行程序test,当在gdb中打了断点,再r了一下之后
gdb就会启动test,生成进程
此是gdc的调试进度就会停在打的断点处,此时由test生成的进程就处于t状态
因为我们如果在gdb上按一下n或者s,test生成的进程就会被执行一下(因为要跑一下那句代码,看会怎么样)
此时这个进程的状态会非常短暂地变成运行状态(因为只有运行能被CPU执行代码),然后又会变成t状态
这就是可追踪的含义
Z状态:
当进程任务完成后
需要向父进程[一般是父进程,也有可能是操作系统]汇报任务情况(是否正确完成/错误码)
这个过程进程就处于Z状态
进程创建的时候,是先创建它对应的内核数据结构[PCB]再加载它的代码和数据
就像考进一个学校,再拿到录取通知书之前你的信息就已经被学校记录在学生管理系统里面了,所以在你人进入学校之前,就有了你对应的数据对象了
而进程退出是则是反过来,即先释放代码和数据,再处理PCB
因为进程退出后,就不会再执行代码了,所以代码和数据没有存在的必要了
但是由于要在PCB里面存储退出信息(描述任务执行状态),给父进程/操作系统读取,所以PCB还不能直接释放
处于Z状态的进程不能再被杀死,因为它本质上已经死了
所以只能让父进程去回收它
如果父进程一直不去回收处于Z状态的子进程就会出现僵尸问题:

进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。父进程如果一直不读取,那子进程就一直处于Z状态
维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task. struct(PCB)中, 换句话说,Z状态一直不退出,内核就必须一直维护它的PCB
那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费即内存泄漏
是的!
因为数据结构对象本身就要占用内存,想想C语言中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!
如何避免?后面会讲。
孤儿进程
如果父进程创建子进程之后,子进程还在运行时,父进程就挂了
此时因为必须要有人在子进程退出时,获取子进程的退出信息以及对子进程进行回收
所有子进程必须再找一个爹,这个爹就是操作系统
所以子进程运行时父进程挂了,子进程被操作系统领养的
此时,这个子进程就叫孤儿进程
X状态:
进程完成Z状态的汇报任务,并且父进程回收完成之后
进程真正死亡时,就处于X状态
进程的优先级
什么是优先级,为什么要有优先级?

需要进程竞争,但是所有进程一拥而上是肯定不行的
这个时候就得排队,那么谁排在前面就是优先级的体现
进程优先级的实现:

如果我们要修改一个进程的优先级
一般修改的是它的nice(NI)值,通过这个间接修改进程的优先级
为什么?
因为如果没有nice值,直接修改PRI值
如果该进程正在运行,就不好判断是否要继续执行
但是修改nice值,就可以等运行暂时结束之后(时间片耗尽等),操作系统就会自动加上NI中存储的值,借此改变优先级
重置进程优先级

为什么每次修改进程的优先级时,pri固定是80?
因为这样可以让用户更方便地修改,就不需要在修改前查看进程之前的优先级了,直接就可以修改
为什么用户可以修改的nice值拥有一个范围?
这是因为我们使用的操作系统绝大部分都是分时操作系统
分时操作系统追求的就是进程调度尽量公平
如果一个用户把自己的一个进程的优先级调的特别高,那么其他用户的进程就有可能一直无法调度
这显然并不公平
进程切换
切换过程的理解

注意:
上图中被红色半圈圈起来的临时数据,指的就是进程的上下文数据
它们在这个进程运行到时候,存储在CPU里面的各种各样的寄存器中,并且随着进程运行不断地发生变化
eip(pc):是一个寄存器
里面存储了正在运行的那句代码(指令)的下一句代码
方便CPU获取
ir:也是寄存器,存储的就是正在CPU中运行的代码(指令)
所以CPU运行进程的简单过程就是:
①把进程接下来要运行的代码的地址,加载到eip寄存器中
②CPU通过eip中的地址找到汇编代码
③把找到的汇编代码放进ir寄存器中
④让eip存储下一条汇编代码的地址
⑤把ir中的汇编代码加载到控制器中运行
第①步只在进程刚开始被CPU调度时执行,②③④⑤则是不断循环,借此实现进程运行
进程切换的时候,把CPU中相关寄存器中的上下文数据保存在了自己的PCB中
切换回来的时候,直接再把上下文数据加载到CPU中对应的寄存器中,就可以继续运行了
进程的调度
运行队列(runqueue)中的调度队列(runqueue中的queue中的queue[140])的结构:

如上图所示,调度队列是一个哈希桶的结构,相同优先级的进程会被放进同一个桶中
CPU调用进程的时候从左往右进行调用,如果一个桶中有进程,就直接拿着桶里的第一个元素调度(插入进程也是头插)
如果没有就继续向后遍历
这样调用就可以体现出优先级了
而runqueue中有两个类型为queue的结构体变量
如图:

这两个结构体变量中的
task_struct* queue[140],就是上面提到的存放进程的PCB的哈希桶
这两个结构体在runqueue中被放在一个数组中
并且定义了两个同类型的指针(active和expired)指向分别指向这两个结构体变量
具体示意图如下:

所以进程调度只需要从active指向的queue里面的哈希桶中从上到下遍历调用即可
调度过程中,会出现如下3种情况
①进程的代码被全部执行完,进程退出
那么这个进程的PCB当然也就不会再回到调度队列中
②进程的时间片耗尽
③新来了进程
②和③情况的进程肯定是要进入调度队列的,但是它们都只会进入expired指向queue里面的哈希桶中
为什呢?
如果②和③情况的进程再进入active指向的queue里面的哈希桶中
此时如果②和③情况的进程的优先级很高,而且这样的进程很多
那它们就会一直插在哈希桶的最前面
那CPU每次调用的时候就都只会调用到它们
比它们优先级更低的进程就根本没有机会被调度了
这不符合分时操作系统的调度原则:进程调度尽可能公平
所以新进程和时间片耗尽的进程就根据自己的优先级,插入expired指向queue里面的哈希桶中
所以
active指向的queue里面的进程,因为没有补充,所以会一直减少,直到减到0
此时只需要交换active和expired的指向的队列,之前队列里面积压的进程就给了active
就可以实现调度轮转[因为CPU只从active指向的queue里面的哈希桶中选进程]
这样调度就既可以保证公平,也体现了进程的优先级
相关文章:
进程(下)【Linux操作系统】
文章目录 进程的状态R状态:S状态:D状态:T状态t状态Z状态:孤儿进程X状态: 进程的优先级如果我们要修改一个进程的优先级重置进程优先级 进程切换进程的调度 进程的状态 在内核中,进程状态的表示,…...
Insar结合ISCE2,某一个文件进行并行-stackSentinel.py
stackSentinel.py 依次执行 run_01 到 run_15,记录各自的日志 并行执行 run_16 里的所有命令,仍然记录日志 不知道对不对,测试的时间有点长就给停了 #!/bin/bash# ✅ 适用于 WSL/Linux runfiles_path"/mnt/e/insar_order_test/Stack…...
2.2.3 TCP—UDP-QUIC
文章目录 2.2.3 TCP—UDP-QUIC1. TCP如何做到可靠性传输1. ACK机制2. 重传机制3. 序号机制4. 窗口机制5. 流量机制6. 带宽机制 2. tcp和udp如何选择1. tcp和udp格式对比2. ARQ协议(Automatic Repeat reQuest,自动重传请求)1. ARQ协议的主要类…...
golang从入门到做牛马:第十九篇-Go语言类型转换:数据的“变形术”
在Go语言中,类型转换是一种将一种数据类型的变量转换为另一种类型的变量的操作。类型转换在处理不同类型的数据时非常有用,尤其是在需要将数据从一种类型转换为另一种类型进行计算或存储时。接下来,让我们一起深入了解Go语言中的类型转换。 什么是类型转换:数据的“变形术”…...
【Golang】第一弹-----初步认识GO语言
笔上得来终觉浅,绝知此事要躬行 🔥 个人主页:星云爱编程 🔥 所属专栏:Golang 🌷追光的人,终会万丈光芒 🎉欢迎大家点赞👍评论📝收藏⭐文章 一、Go语言的简单介绍 1、G…...
K8S学习之基础二十三:k8s的持久化存储之nfs
K8S持久化存储之nfs 在 Kubernetes (k8s) 中使用 NFS(Network File System)作为存储解决方案是一种常见的方式,特别是在需要共享存储的场景中。以下是关于如何在 Kubernetes 中使用 NFS 存储的详细说明: 1. 准备 NFS 服务器 …...
【Linux通信篇】深入理解进程间通信——管道
--------------------------------------------------------------------------------------------------------------------------------- 每日鸡汤:找一个对的人,然后好好去爱。一个你跟他在一起,然后又可以舒舒服服做自己的人。 -------…...
「 DelegateUI 」Ant-d 风格的 Qt Qml UI 套件
写在前面:关于为什么要写一套新的UI框架 一方面,Qt Qml 生态中缺乏一套既遵循现代设计规范(自带的功能少且丑,懂得都懂),又能深度整合 Qt 生态的开源组件库。 另一方面,Qt Qml 中也有一些其他方案,例如 FluentUI Qml…...
Redis--Set类型
目录 一、引言 二、介绍 三、命令 1.sadd,smembers,sismember 2.spop,srandmember 3.smove,srem 4.sinter,sinterstore 5.sunion,sunionstore,sdiff,sdiffstore 四、内部编码 1.intset 2.hashtable 五、应用场景 1.使用Set保存用…...
【0013】Python数据类型-列表类型详解
如果你觉得我的文章写的不错,请关注我哟,请点赞、评论,收藏此文章,谢谢! 本文内容体系结构如下: Python列表,作为编程中的基础数据结构,扮演着至关重要的角色。它不仅能够存储一系…...
文件上传靶场(10--20)
目录 实验环境: 具体内容实现: 第十关(双写绕过): 第十一关:(%00截断,此漏洞在5.2版本中) 正确用法 错误用法 思路: 操作过程: 第十二关…...
C# 检查系统是否开启 Hyper - V
C# 检查系统是否开启 Hyper - V 在使用 C# 开发应用程序时,有时需要判断系统是否开启了 Hyper - V 功能。Hyper - V 是 Windows 系统提供的一款虚拟化技术,以下为你介绍几种在 C# 中检查系统是否开启 Hyper - V 的方法。 方法一:通过查询系…...
【前端】BOM DOM
两天更新完毕,建议关注收藏点赞 友情链接: HTML&CSS&LESS&Bootstrap&Emmet Axios & AJAX & Fetch BOM DOM 待整理 js2 Web API 是浏览器提供的一套操作浏览器功能和页面元素的 API ( BOM 和 DOM)。官方文档点击跳转 目录 BOMDOM…...
K8s 1.27.1 实战系列(十一)ConfigMap
ConfigMap 是 Kubernetes 中管理非敏感配置的核心资源,通过解耦应用与配置实现灵活性和可维护性。 一、ConfigMap 的核心功能及优势 1、配置解耦 将配置文件(如数据库地址、日志级别)与容器镜像分离,支持动态更新而无需重建镜像。 2、多形式注入 环境变量:将键值…...
计算机网络——IP、MAC、ARP
一、IP地址 1. 什么是IP地址? IP地址(Internet Protocol Address)是互联网中设备的唯一逻辑标识符,类似于现实生活中的“门牌号”。它分为 IPv4(32位,如 192.168.1.1)和 IPv6(128位…...
代码优化——基于element-plus封装组件:表单封装
前言 今天实现一个基于element-plus表单组件的二次封装,什么是二次封装?查看以下表单,传统表单组件是不是用<el-form>嵌套几个<el-form-item>即可实现,那么一个表单可不可以实现,传入一个对象给封装组件&a…...
C/C++中使用CopyFile、CopyFileEx原理、用法、区别及分别在哪些场景使用
文章目录 1. CopyFile原理函数原型返回值用法示例适用场景 2. CopyFileEx原理函数原型返回值用法示例适用场景 3. 核心区别4. 选择建议5. 常见问题6.区别 在Windows系统编程中,CopyFile和CopyFileEx是用于文件复制的两个API函数。它们的核心区别在于功能扩展性和控制…...
qt 多进程使用共享内存 ,加速数据读写,进程间通信 共享内存
Summary: 项目中我们有时需要使用共享内存共享数据,这样,数据不用进程IO读写,加进数据加载和落地; 程序退出时,再保存到本地;速度提升数十倍; Part1:QSharedMemory Windows平台下进程间通信…...
HTML左右分页2【搬代码】
HTML左右分页2 html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>左右分页布局</title>&l…...
【鸿蒙开发】OpenHarmony调测工具hdc使用教程(设备开发者)
00. 目录 文章目录 00. 目录01. OpenHarmony概述02. hdc简介03. hdc获取04. option相关的命令05. 查询设备列表的命令06. 服务进程相关命令07. 网络相关的命令08. 文件相关的命令09. 应用相关的命令10. 调试相关的命令11. 常见问题12. 附录 01. OpenHarmony概述 OpenHarmony是…...
【贪心算法】简介
1.贪心算法 贪心策略:解决问题的策略,局部最优----》全局最优 (1)把解决问题的过程分成若干步 (2)解决每一步的时候,都选择当前看起来的“最优”的算法 (3)“希望”得…...
transformer模型介绍——大语言模型 LLMBook 学习(二)
1. transformer模型 1.1 注意力机制 **注意力机制(Attention Mechanism)**在人工智能中的应用,实际上是对人类认知系统中的注意力机制的一种模拟。它主要模仿了人类在处理信息时的选择性注意(Selective Attention)&a…...
【GPT入门】第11课 FunctionCall调用本地代码入门
【GPT入门】第11课 FunctionCall调用代码入门 1. 手撕FunctionCall2.代码3.functionCall的结果 1. 手撕FunctionCall 为了了解,funcationCall底层,手写一个functionCall多方法,并调用,体验 思路: 任务:让…...
LangChain教程 - Agent -之 ZERO_SHOT_REACT_DESCRIPTION
在构建智能 AI 助手时,我们希望模型能够智能地调用工具,以便提供准确的信息。LangChain 提供了 AgentType.ZERO_SHOT_REACT_DESCRIPTION,它结合了 ReAct(Reasoning Acting)策略,使得 LLM 可以基于工具的描…...
GStreamer —— 2.17、Windows下Qt加载GStreamer库后运行 - “播放教程 5:色彩平衡“(附:完整源码)
运行效果 介绍 亮度、对比度、色相和饱和度是常见的视频调整, 在 GStreamer 中统称为 Color Balance 设置。 本教程展示了: • 如何找出可用的色彩平衡通道 • 如何更改它们 允许访问颜色平衡设置。如果 元素支持这个接口,只需将其转发给应用…...
串口通信ASCII码转16进制及C#串口编程完整源码下载
在工业自动化、嵌入式系统及物联网以行业中,串口编程非常重要。 串口编程,重点在于串口数据通信和数据处理。 在C#中,System.IO.Ports命名空间提供了SerialPort类,用于实现串口通信。 串口程序的开发主要包括以下几点 1.引用命…...
解决vscode中出现“无法将pip项识别...“问题
问题 遇见问题如下: 查看pip 通过 winR ,输入 cmd,进入终端,搜索 where pip。 发现 pip 查不出来,然后进入文件资源管理器,搜索 Scripts 文件夹,如果没有找到可能是电脑没有下载 python。 点击…...
nacos下载及安装
下载官方最新稳定版 github下载较慢,推荐下面的下载链接 Nacos Server 下载 | Nacos 官网 点击下载和试用下载最新稳定版 Nacos Server 下载 | Nacos 官网 配置检查(可选) 默认情况下,Nacos 使用内置的 Derby 数据库&#x…...
C++从零实现Json-Rpc框架
文章目录 一、项目介绍1. 基本原理2. 涉及到的技术栈3. 最终实现的效果 二、 第三方库的介绍与使用1. JsonCpp库Json的数据格式JsonCpp介绍封装Json工具类 2. muduo库muduo库是什么Muduo库常见接口介绍 3. C11异步操作std::future 三、框架设计1. 服务端模块划分NetworkProtoco…...
rom定制系列------小米note3 原生安卓15 批量线刷 默认开启usb功能选项 插电自启等
小米Note 3搭载骁龙660处理器,1200万像素广角镜头、俗称大号版的小米6,官方最终版为12.0.1稳定版安卓9的固件。客户需要运行在安卓15的rom。根据原生官网的rom修改一些功能选项。以便客户操作需求。 定制资源说明 根据客户需求采用安卓15原生系统为底包…...
