【Linux】深入理解进程状态、优先级和调度:Linux 内核中的实现原理探析

文章目录

  • 前言
  • 1. 进程状态
    • 1.1. 轻量进程排队这件事情——队列
    • 1.2. 进程状态的表述及其影响:
    • 1.3. 挂起状态及处理:
    • 1.4.理解 Linux 内核源代码中的状态表述:
  • 2. 进程优先级
    • Linux 为什么要调整优先级是要受限的?
  • 3. Linux的调度与切换
    • 3.1. 进程调度:
    • 3.2. 进程切换(并发):
      • Linux 实现进程调度和切换的机制主要包括以下几个方面:
  • 总结

前言

在计算机操作系统中,进程状态、优先级和调度是非常重要的概念,它们直接影响着系统的性能、资源利用率和响应速度。理解这些概念不仅对于系统管理员和开发人员来说至关重要,对于任何对计算机系统有兴趣的人都是有益的。

本文将深入探讨进程状态的各种表述方式、影响因素以及在 Linux 内核源代码中的具体实现,以及进程优先级的概念及其在 Linux 中的实现方式。我们还将讨论进程调度和切换的原理,以及 Linux 内核是如何通过各种机制来管理和调度进程,确保系统资源的合理利用和进程之间的公平竞争。

1. 进程状态

1.1. 轻量进程排队这件事情——队列

  • 进程由 task_struct 和可执行程序组成。
  • 进程排队意味着 task_struct 排队,通常是等待某种资源。
  • 一个 task_struct 可以被连接到多种数据结构中,底层队列通常使用链表实现,Linux 中记录偏移量。

1.2. 进程状态的表述及其影响:

  • 状态本质上是 task_struct 中的一个整型变量。
#define New 1
#define Ready 2
#define runing 3
#define running 3
#define block 3
...
  • 状态决定了什么?
    状态决定了进程的后续动作,例如任务的调度。
    Linux中可能会有很多个进程都要根据它的状态执行后续的动作(进程排队了!)
struct runqueue{
	int num;
	task_struct *q;
}	
  • Linux 中的状态包括运行、阻塞、挂起等,由整型变量表示,例如:

运行状态(R):表示进程准备好随时被调度。
阻塞状态(S):表示进程等待软硬件资源,可中断睡眠。
不可中断睡眠(D):表示进程等待硬件资源。
挂起状态(T):暂停进程的执行,让其处于暂停状态,等待其他事件发生。

一个 CPU 一个运行队列, 其中运行状态不仅仅是在CPU上跑,只要是在运行队列里排队的进程都属于运行状态 。
R状态:我以及准备好随时被调度了!

1.3. 挂起状态及处理:

  • 挂起状态在计算机资源紧张时发生。
  • 阻塞挂起状态是进程等待资源时的一种状态。
  • 当进程等待软硬件资源时,如果资源未就绪,进程的 task_struct 可能被置为阻塞状态,并连接到资源提供的等待队列。
  • 状态变迁导致 task_struct 被移动到不同的队列中,以便操作系统进行管理。

1.4.理解 Linux 内核源代码中的状态表述:

为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)。
下面的状态在kernel源代码里定义:

/*
* 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[] = {
"R (running)", /* 0 */ // 运行状态
"S (sleeping)", /* 1 */ // 阻塞状态(可中断睡眠:浅度睡眠)
"D (disk sleep)", /* 2 */ // 不可中断睡眠:深度睡眠
"T (stopped)", /* 4 */  // 让进程处于暂停状态
"t (tracing stop)", /* 8 */ // 被追踪专题
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
  • Linux 内核中使用数组定义了进程的不同状态,如运行状态(R)、睡眠状态(S)、不可中断睡眠(D)等。
  • 进程状态数组以位图形式表示,可以通过简单的位测试来检测状态组合。
  • 例如,Z(zombie)状态表示进程已经退出,但其状态需要保持,以供上层读取,避免内存泄漏。
  • 为什么要有Z状态? 创建进程是希望这个进程给用户完成工作的,子进程必须得有结果数据,pcb中的。
  • 什么是Z?进程已经退出,但是当进程的状态需要维持住,供上层读取,必须处于Z
  • 如果我父亲不读取呢?僵尸状态,会一直存在。task_struct 对象也一直存在,都是要占内存的。内存泄漏!

在这里插入图片描述

2. 进程优先级

  • 进程优先级是什么?
    前提:进程要访问某种资源,进程进行通过一定的方式(排队),确认享受资源的先后顺序。
  • 为什么?资源过少!(相对的概念)
  • 怎么办?
struct task_struct
{
	// 优先级
	int PRI;
	int nice;
}

在Linux系统中,进程优先级由一个整数表示,范围一般在[60, 99]之间,默认优先级是80。数字越小,优先级越高,进程越有可能先获取系统资源。Linux允许用户调整进程的优先级,但通常不直接修改优先级值(PRI),而是通过调整nice值(nice是进程优先级的修正数据),范围在[-20, 19]之间。负值表示更高的优先级,正值表示更低的优先级。

Linux 为什么要调整优先级是要受限的?

这是因为如果不加限制,有可能出现某些进程将自己的优先级调整得非常高,而其他进程则调整得非常低的情况,从而导致系统资源被不合理地分配。高优先级的进程会优先获取CPU等系统资源,而低优先级的进程可能会长时间无法执行,造成资源饥饿问题。

任何的分时操作系统,在调度上,较为公平的调度。

3. Linux的调度与切换

在 Linux 中,进程调度和切换是操作系统中重要的机制,它们确保了系统资源的合理利用和进程之间的公平竞争。下面是关于进程调度和切换的一些概念:

3.1. 进程调度:

  • 系统中的进程数目通常远远多于可用的 CPU 数目,因此进程之间存在竞争关系。为了高效地完成任务,系统通过进程调度算法来决定何时执行哪个进程。
  • 进程调度算法通常基于进程的优先级、等待时间、历史运行情况等因素来进行决策,以最大程度地提高系统整体的效率和吞吐量。

概念准备:

  1. 进程在运行的时候,放在CPU上,直接必须把进程代码跑完,才行吗?不对。现代操作系统都是,基于时间篇进行轮转的。
  2. 关于竞争性、独立性、并行和并发的概念
  • 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有- 竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。
  • 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰。
  • 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行。
  • 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。

3.2. 进程切换(并发):

  • 在多任务操作系统中,多个进程会共享 CPU 资源。当一个进程的时间片用完或者发生阻塞等情况时,操作系统需要切换到另一个进程,以保证系统的响应性和效率。
  • 进程切换涉及保存和恢复进程的上下文信息,包括寄存器状态、内存映射、进程状态等。这些信息被保存在操作系统内部数据结构中,以便在需要时进行切换和恢复。

进程在运行过程中产生的临时数据,以及关于硬件上下文的保存和恢复:

  1. 进程的临时数据:
  • 在执行过程中,进程会产生大量的临时数据,例如变量、函数调用栈等。这些临时数据通常存储在内存中的堆栈段或堆段中,以供程序运行时使用。
  1. 硬件上下文:
  • 当一个进程被调度执行时,CPU 需要保存当前进程的硬件上下文,包括寄存器中的数据、程序计数器(PC)等信息。这些信息构成了进程在 CPU 上运行的环境和状态,称为硬件上下文。
  1. 硬件上下文的保存和恢复:
  • 当进程被调度暂停或切换时,CPU 会将当前进程的硬件上下文保存到内存中,以便稍后恢复。而当该进程再次被调度执行时,CPU 会从内存中恢复之前保存的硬件上下文,使得进程可以从上次执行的位置继续执行。
  1. 区分寄存器和寄存器的内容:
  • CPU 内部的寄存器只有一组,它们用于存储当前正在执行的指令、操作数等关键信息。
  • 寄存器内部保存的数据可以有多套,每个进程都有自己的一套寄存器数据,被称为进程的上下文信息。虽然这些寄存器都是在共享的 CPU 中,但不同进程的寄存器数据是相互隔离的,每个进程都无法直接访问其他进程的寄存器数据。

Linux 实现进程调度和切换的机制主要包括以下几个方面:

  • 使用优先级队列管理进程,以确保高优先级进程优先执行。
  • 考虑进程饥饿问题,避免低优先级进程长时间无法执行的情况发生。
  • 实现时间片轮转调度算法,确保每个进程都有机会执行,并防止某个进程长时间占用 CPU 资源。
  • 使用位图等数据结构记录不同优先级队列的状态,以便高效地选择下一个要执行的进程。
  • 在进程切换时,保存和恢复进程的硬件上下文信息,确保进程能够从切换前的状态无缝地继续执行。 swap(&active, &expried);

总结

本文介绍了进程状态、优先级和调度在计算机操作系统中的重要性和原理。通过对进程状态的各种表述方式和影响因素的讨论,我们了解了进程在操作系统中的不同状态及其意义,以及在 Linux 内核源代码中的具体实现方式。进程优先级的概念及其在 Linux 中的实现方式也得到了阐述,包括通过调整 nice 值来调整进程的优先级。最后,我们深入探讨了进程调度和切换的原理,以及 Linux 内核是如何通过各种机制来管理和调度进程,确保系统资源的合理利用和进程之间的公平竞争。

通过对这些关键概念的理解,我们能够更好地管理和优化系统资源的利用,提高系统的性能和响应速度,从而为用户提供更好的计算机体验。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Typora下载激活方案

一、下载 1.在typora官网下载最新版本,并安装: 官网地址 2.获取激活工具 感谢Typora激活方法(2023年最新版) - AI小智的文章 - 知乎 https://zhuanlan.zhihu.com/p/669618741 二、激活 1.把两个.exe文件复制到typora安装目录下 2.在typor…

ubuntu下给不同串口设置别名

目录 一、绑定设备ID 1.查看设备ID 2.编写usev规则 3.重新加载usev规则 4.查看 二、绑定USB端口号 1.先插入一个串口,查看USB设备信息 2.查看USB转串口信息 3.编写usev规则 4.重新加载usev规则 5.查看 在Ubuntu环境下,有时候工控机或者arm开…

推挽输出与开漏输出

推挽输出与开漏输出 文章目录 推挽输出与开漏输出前言一、推挽输出二、开漏输出总结 前言 在使用GPIO口时,会遇到两种配置,一种叫推挽输出,一种叫开漏输出,今天就简聊一聊这两种模式的差异和选择。 一、推挽输出 如图所示&#…

Lazarus远控组件NukeSped分析

静态信息: 样本md5:9b656f5d7e679b94e7b91fc3c4f313e4 由此可见为假的Adobe Flash Player 的攻击样本 样本分析 通过五个函数,内部调用sub_40159D函数动态获取API函数 利用IDA python解密字符串。。 完整python代码 Python> idc.get_…

扫雷(蓝桥杯)

题目描述 小明最近迷上了一款名为《扫雷》的游戏。其中有一个关卡的任务如下, 在一个二维平面上放置着 n 个炸雷,第 i 个炸雷 (xi , yi ,ri) 表示在坐标 (xi , yi) 处存在一个炸雷,它的爆炸范围是以半径为 ri 的一个圆。 为了顺利通过这片土…

Mac air 个人免费版VMWare Fusion安装及配置教程

Mac air 安装免费版VMWare Fusion教程及问题解决 1、下载VMWare Fusion2、下载wins镜像文件3、开始配置4、出现的问题及解决方法4.1 如何跳过启动时的网络连接4.2 启动后,无法连接网络怎么办4.3 怎么实现将文件拖拽到虚拟机中 当你手上是一台Mac电脑,却需…

【博弈论3——二人博弈的纳什均衡】

1.俾斯麦海之战 2. 零和博弈的定义 零和博弈(Zero-Sum Game)是一种博弈论的基本概念,指的是在博弈过程中,博弈参与者之间的收益和损失之和总是一个常数,特别是总和为零。即博弈一方的收益必然等于另一方的损失&#x…

RCG自条件是如何添加到 Pixel Generator上的?

在自条件的训练过程中,需要将图像经过Pretrained encoder的表征Rep输入进已有的Pixel Generator上,目前RCG是向四种Pixel Generator上加入了自条件,关于它是如何将rep加到Pixel Generator上的,我来总结一下: 一、Pixel…

[SpringCloud] Feign Client 的创建 (一) (四)

文章目录 1.FeignClientsRegistrar2.完成配置注册2.1 registerDefaultConfiguration方法2.2 迭代稳定性2.3 registerFeignClients方法 1.FeignClientsRegistrar FeignClientsRegistrar实现ImportBeanDefinitionRegistrar接口。 2.完成配置注册 public void registerBeanDefinit…

JQ 查看图片的好插件

效果图 插件官网 https://blog.51cto.com/transfer?https://github.com/fengyuanchen/viewer 使用 <!DOCTYPE html> <html lang"en"> <head><meta charset"utf-8"><link rel"stylesheet" href"css/viewer.c…

攻防世界——catfly

这道题我觉得很难&#xff0c;我当初刷题看见这道题&#xff0c;是唯一一道直接跳过的&#xff0c;现在掌握了一点知识才回来重新看 这道题在linux运行下是这样&#xff0c;我首先猜测是和下面这个time有关&#xff0c;判断达到一定次数就会给我flag 但是我找了好久都没找到那…

(九)信息融合方式简介

目录 前言 一、什么是信息融合&#xff1f; 二、集中式信息融合与分布式信息融合 &#xff08;一&#xff09;集中式融合 &#xff08;二&#xff09;分布式融合 1.简单信息融合 2.CI&#xff08;协方差交叉&#xff09;信息融合 3.无反馈的最优分布式融合 4.有反馈的…

反应式编程(一)什么是反应式编程

目录 一、背景二、反应式编程简介2.1 定义2.2 反应式编程的优势2.3 命令式编程 & 反应式编程 三、Reactor 入门3.1 Reactor 的核心类3.2 Reactor 中主要的方法1&#xff09;创建型方法2&#xff09;转化型方法3&#xff09;其他类型方法4&#xff09;举个例子 四、Reactor …

论文笔记:GPT-4 Is Too Smart To Be Safe: Stealthy Chat with LLMs via Cipher

ICLR 2024 reviewer评分 5688 1 论文思路 输入转换为密码&#xff0c;同时附上提示&#xff0c;将加密输入喂给LLMLLM输出加密的输出加密的输出通过解密器解密 ——>这样的步骤成功地绕过了GPT-4的安全对齐【可以回答一些反人类的问题&#xff0c;这些问题如果明文问的话&…

【C++】set和map

set和map就是我们上篇博客说的key模型和keyvalue模型。它们属于是关联式容器&#xff0c;我们之前说过普通容器和容器适配器&#xff0c;这里的关联式容器就是元素之间是有关联的&#xff0c;通过上篇博客的讲解我们也对它们直接的关系有了一定的了解&#xff0c;那么下面我们先…

蓝桥杯-python-常用库归纳

目录 日期和时间 datetime模块 date日期类&#xff0c;time时间类&#xff0c;datetime日期时间类 定义date&#xff08;年&#xff0c;月&#xff0c;日&#xff09; data之间的减法 定义时间&#xff08;时&#xff0c;分&#xff0c;秒&#xff09; 定义datetime&#xf…

42.HarmonyOS鸿蒙系统 App(ArkUI)实现横屏竖屏自适应

HarmonyOS鸿蒙系统 App(ArkUI)实现横屏竖屏自适应 媒体查询作为响应式设计的核心&#xff0c;在移动设备上应用十分广泛。媒体查询可根据不同设备类型或同设备不同状态修改应用的样式。媒体查询常用于下面两种场景&#xff1a; 针对设备和应用的属性信息&#xff08;比如显示…

【Linux】进程实践项目 —— 自主shell编写

送给大家一句话&#xff1a; 不管前方的路有多苦&#xff0c;只要走的方向正确&#xff0c;不管多么崎岖不平&#xff0c;都比站在原地更接近幸福。 —— 宫崎骏《千与千寻》 自主shell命令编写 1 前言2 项目实现2.1 创建命令行2.2 获取命令2.3 分割命令2.4 运行命令 3 源代码…

计算机服务器中了rmallox勒索病毒怎么办?rmallox勒索病毒解密数据恢复

网络技术的不断发展与应用&#xff0c;大大提高了企业的生产运营效率&#xff0c;越来越多的企业开始网络开展各项工作业务&#xff0c;网络在为人们提供便利的同时&#xff0c;也会存在潜在威胁。近日&#xff0c;云天数据恢复中心接到多家企业的求助&#xff0c;企业的计算机…

Python内置函数enumerate()

Python的内置函数enumerate()。在学习过程中遇到了一点小问题。记录一下。 enumerate() 是 Python 中常用的内置函数之一&#xff0c;它可以用来同时遍历序列的索引和对应的值。具体来说&#xff0c;enumerate() 接受一个可迭代对象作为参数&#xff0c;返回一个包含索引和值的…