进程(下)【Linux操作系统】

news2025/3/13 5:24:53

文章目录

  • 进程的状态
    • 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里面的哈希桶中选进程]

这样调度就既可以保证公平,也体现了进程的优先级


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

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语言

笔上得来终觉浅,绝知此事要躬行 🔥 个人主页:星云爱编程 🔥 所属专栏:Golang 🌷追光的人,终会万丈光芒 🎉欢迎大家点赞👍评论📝收藏⭐文章 一、Go语言的简单介绍 1、G…

K8S学习之基础二十三:k8s的持久化存储之nfs

K8S持久化存储之nfs ​ 在 Kubernetes (k8s) 中使用 NFS(Network File System)作为存储解决方案是一种常见的方式,特别是在需要共享存储的场景中。以下是关于如何在 Kubernetes 中使用 NFS 存储的详细说明: 1. 准备 NFS 服务器 …

【Linux通信篇】深入理解进程间通信——管道

--------------------------------------------------------------------------------------------------------------------------------- 每日鸡汤:找一个对的人,然后好好去爱。一个你跟他在一起,然后又可以舒舒服服做自己的人。 -------…

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版本中) 正确用法 错误用法 思路: 操作过程: 第十二关…

【前端】BOM DOM

两天更新完毕,建议关注收藏点赞 友情链接: HTML&CSS&LESS&Bootstrap&Emmet Axios & AJAX & Fetch BOM DOM 待整理 js2 Web API 是浏览器提供的一套操作浏览器功能和页面元素的 API ( BOM 和 DOM)。官方文档点击跳转 目录 BOMDOM…

计算机网络——IP、MAC、ARP

一、IP地址 1. 什么是IP地址? IP地址(Internet Protocol Address)是互联网中设备的唯一逻辑标识符,类似于现实生活中的“门牌号”。它分为 IPv4(32位,如 192.168.1.1)和 IPv6(128位…

代码优化——基于element-plus封装组件:表单封装

前言 今天实现一个基于element-plus表单组件的二次封装&#xff0c;什么是二次封装&#xff1f;查看以下表单&#xff0c;传统表单组件是不是用<el-form>嵌套几个<el-form-item>即可实现&#xff0c;那么一个表单可不可以实现&#xff0c;传入一个对象给封装组件&a…

C/C++中使用CopyFile、CopyFileEx原理、用法、区别及分别在哪些场景使用

文章目录 1. CopyFile原理函数原型返回值用法示例适用场景 2. CopyFileEx原理函数原型返回值用法示例适用场景 3. 核心区别4. 选择建议5. 常见问题6.区别 在Windows系统编程中&#xff0c;CopyFile和CopyFileEx是用于文件复制的两个API函数。它们的核心区别在于功能扩展性和控制…

qt 多进程使用共享内存 ,加速数据读写,进程间通信 共享内存

Summary: 项目中我们有时需要使用共享内存共享数据&#xff0c;这样&#xff0c;数据不用进程IO读写&#xff0c;加进数据加载和落地&#xff1b; 程序退出时&#xff0c;再保存到本地&#xff1b;速度提升数十倍&#xff1b; Part1:QSharedMemory Windows平台下进程间通信…

【鸿蒙开发】OpenHarmony调测工具hdc使用教程(设备开发者)

00. 目录 文章目录 00. 目录01. OpenHarmony概述02. hdc简介03. hdc获取04. option相关的命令05. 查询设备列表的命令06. 服务进程相关命令07. 网络相关的命令08. 文件相关的命令09. 应用相关的命令10. 调试相关的命令11. 常见问题12. 附录 01. OpenHarmony概述 OpenHarmony是…

【贪心算法】简介

1.贪心算法 贪心策略&#xff1a;解决问题的策略&#xff0c;局部最优----》全局最优 &#xff08;1&#xff09;把解决问题的过程分成若干步 &#xff08;2&#xff09;解决每一步的时候&#xff0c;都选择当前看起来的“最优”的算法 &#xff08;3&#xff09;“希望”得…

transformer模型介绍——大语言模型 LLMBook 学习(二)

1. transformer模型 1.1 注意力机制 **注意力机制&#xff08;Attention Mechanism&#xff09;**在人工智能中的应用&#xff0c;实际上是对人类认知系统中的注意力机制的一种模拟。它主要模仿了人类在处理信息时的选择性注意&#xff08;Selective Attention&#xff09;&a…

GStreamer —— 2.17、Windows下Qt加载GStreamer库后运行 - “播放教程 5:色彩平衡“(附:完整源码)

运行效果 介绍 亮度、对比度、色相和饱和度是常见的视频调整&#xff0c; 在 GStreamer 中统称为 Color Balance 设置。 本教程展示了&#xff1a; • 如何找出可用的色彩平衡通道 • 如何更改它们 允许访问颜色平衡设置。如果 元素支持这个接口&#xff0c;只需将其转发给应用…

串口通信ASCII码转16进制及C#串口编程完整源码下载

在工业自动化、嵌入式系统及物联网以行业中&#xff0c;串口编程非常重要。 串口编程&#xff0c;重点在于串口数据通信和数据处理。 在C#中&#xff0c;System.IO.Ports命名空间提供了SerialPort类&#xff0c;用于实现串口通信。 串口程序的开发主要包括以下几点 1.引用命…

解决vscode中出现“无法将pip项识别...“问题

问题 遇见问题如下&#xff1a; 查看pip 通过 winR &#xff0c;输入 cmd&#xff0c;进入终端&#xff0c;搜索 where pip。 发现 pip 查不出来&#xff0c;然后进入文件资源管理器&#xff0c;搜索 Scripts 文件夹&#xff0c;如果没有找到可能是电脑没有下载 python。 点击…

nacos下载及安装

下载官方最新稳定版 github下载较慢&#xff0c;推荐下面的下载链接 Nacos Server 下载 | Nacos 官网 点击下载和试用下载最新稳定版 Nacos Server 下载 | Nacos 官网 配置检查&#xff08;可选&#xff09; 默认情况下&#xff0c;Nacos 使用内置的 Derby 数据库&#x…