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

Linux--进程的调度

1.进程切换

CPU上下⽂切换:其实际含义是任务切换, 或者CPU寄存器切换。当多任务内核决定运⾏另外的任务时, 它保存正在运⾏任务的当前状态, 也就是CPU寄存器中的全部内容。这些内容被保存在任务⾃⼰的堆栈中, ⼊栈⼯作完成后就把下⼀个将要运⾏的任务的当前状况从该任务的栈中重新装⼊CPU寄存器,并开始下⼀个任务的运⾏, 这⼀过程就是context switch。

时间⽚:当代计算机都是分时操作系统,没有进程都有它合适的时间⽚(其实就是⼀个计数
器)。时间⽚到达,进程就被操作系统从CPU中剥离下来。

2.Linux内核进程O(1)调度队列

 在前面我们说过进程的状态,在运行状态的进行,是CPU当前要运行的队列,那么CPU要管理它们,总要有个先后顺序吧,因为CPU只有一套寄存器,不能同时运行多个进程,于是就有了运行队列(runqueue),这是一个结构体,专门用于管理运行队列的进程。
⼀个CPU拥有⼀个runqueue,如果有多个CPU就要考虑进程个数的负载均衡问题。

2.1task_struct与runqueue的关系

在 Linux 内核里,task_structrunqueue是进程调度机制中的两个关键数据结构,它们关系紧密,下面为你详细介绍。

2.1.1 核心概念

  • task_struct:这是内核用来表示进程的核心数据结构,也被叫做 "进程描述符"。它把进程的所有信息都整合在一起,像进程状态、优先级、资源分配情况、打开的文件等,都包含其中。
  • runqueue:也就是运行队列,其作用是管理系统中处于可运行状态(TASK_RUNNING)的进程。每个 CPU 核心都有属于自己的runqueue,这样可以实现并行调度。

2.1.2 二者的关联

  • 进程状态的纽带:当进程处于可运行状态时,它会被加入到runqueue中;而当进程处于阻塞状态(比如等待 I/O)时,就会从runqueue中移除。
  • 调度的实现:调度器会从runqueue里挑选出一个进程,让它在对应的 CPU 上运行。挑选进程时依据的是调度算法,像 CFS(完全公平调度)算法,此时task_struct中的se(调度实体)字段就会发挥作用。
  • 负载均衡:内核会在不同 CPU 的runqueue之间进行进程迁移,以此来实现负载均衡,task_struct中的相关指针能帮助定位进程所在的队列。

2.1.3 数据结构层面的联系

下面是用伪代码呈现的它们之间的关键联系:

struct task_struct {// 进程状态volatile long state;        // 例如 TASK_RUNNING// 调度相关struct sched_entity se;     // 调度实体,用于CFS调度器struct list_head run_list;  // 连接到runqueue的链表struct rq *rq;              // 指向所在runqueue的指针int on_rq;                  // 标记进程是否在runqueue中
};struct rq {// 运行队列中的进程struct cfs_rq cfs;          // CFS调度器的运行队列struct list_head run_list;  // 可运行进程的链表unsigned int nr_running;    // 可运行进程的数量// 当前运行的进程struct task_struct *curr;   // 当前正在运行的进程
};

2.1.4 工作流程示例

下面以进程调度为例,说明二者的协作流程:

 
  1. 当进程被创建或者从阻塞状态变为可运行状态时,内核会调用enqueue_task函数,把该进程添加到runqueue中。
  2. 调度器通过pick_next_task函数从runqueue里选择一个最优的进程。
  3. 进程执行过程中,如果时间片用完或者主动放弃 CPU,就会调用dequeue_task函数,将进程从runqueue中移除。
  4. 整个过程中,进程的task_struct会一直维护自身在runqueue中的状态和位置。

2.1.5 总结

task_struct代表着单个进程,而runqueue则负责管理多个可运行的进程,它们共同构成了 Linux 内核调度系统的基础。通过这种进程状态管理和队列操作机制,Linux 内核能够高效地实现多任务处理。

2.2runqueue的运行原理

这里我们可以简单看看runqueue结构体里的变量。

2.2.1活动队列

时间⽚还没有结束的所有进程都按照优先级放在该队列

nr_active: 总共有多少个运⾏状态的进程
queue[140]: ⼀个元素就是⼀个进程队列,相同优先级的进程按照FIFO规则进⾏排队调度,所以 数组下标就是优先级
从该结构中,选择⼀个最合适的进程,过程是怎么的呢?
1. 从0下表开始遍历queue[140]
2. 找到第⼀个⾮空队列,该队列必定为优先级最⾼的队列
3. 拿到选中队列的第⼀个进程,开始运⾏,调度完成!
4. 遍历queue[140]时间复杂度是常数!但还是太低效了!

于是Linux用了一个非常巧妙的方法:

bitmap[5]:⼀共140个优先级,⼀共140个进程队列,为了提⾼查找⾮空队列的效率,就可以⽤5*32个⽐特位表⽰队列是否为空,这样,便可以大大提⾼查找效率!

2.2.2过期队列

过期队列和活动队列结构⼀模⼀样
过期队列上放置的进程,都是时间⽚耗尽的进程
当活动队列上的进程都被处理完毕之后,对过期队列的进程进⾏时间⽚重新计算

2.2.3活跃进程和过期进程的关系

在上图中我们可以看到两块被圈出来的空间,同样的几个变量为什么要有两套呢?

原因就是,当我们CPU调度的时候是在活跃进程表中一一调度,那么当调度完了进程的task_struct要去哪呢?答案是进入过期进程表,这样当我们活跃进场调度完了之后,进程的顺序还是没有乱,我们再把活跃进程列表和过期进程列表swap一下。

2.2.4 active指针和expired指针

active指针永远指向活动队列
expired指针永远指向过期队列
可是活动队列上的进程会越来越少,过期队列上的进程会越来越多,因为进程时间⽚到期时⼀直
都存在的。
没关系,在合适的时候,只要能够交换active指针和expired指针的内容,就相当于有具有了⼀批
新的活动进程!

3.总结

在系统当中查找⼀个最合适调度的进程的时间复杂度是⼀个常数,不随着进程增多⽽导致时间成
本增加,我们称之为进程调度O(1)算法!

相关文章:

Linux--进程的调度

1.进程切换 CPU上下⽂切换:其实际含义是任务切换, 或者CPU寄存器切换。当多任务内核决定运⾏另外的任务时, 它保存正在运⾏任务的当前状态, 也就是CPU寄存器中的全部内容。这些内容被保存在任务⾃⼰的堆栈中, ⼊栈⼯作完成后就把下⼀个将要运⾏的任务的当前状况从该…...

Hadolint:Dockerfile 语法检查与最佳实践验证的终极工具

在容器化应用开发的浪潮中,Dockerfile 作为构建 Docker 镜像的核心配置文件,其质量直接影响着应用的安全性、稳定性和可维护性。然而,随着项目复杂度的增加,手动检查 Dockerfile 不仅耗时,还容易遗漏潜在问题。今天,我要向大家介绍一款强大的工具——Hadolint,它将彻底改…...

Python爬虫实战:研究Hyper 相关技术

一、项目概述 本项目展示了如何结合 Python 的异步编程技术与 Hyper 框架开发一个高性能、可扩展的网络爬虫系统。该系统不仅能够高效地爬取网页内容,还提供了 RESTful API 接口,方便用户通过 API 控制爬虫的运行状态和获取爬取结果。 二、系统架构设计 1. 整体架构 系统采…...

基于langchain的简单RAG的实现

闲来无事,想研究一下RAG的实现流程,看网上用langchain的比较多,我自己在下面也跑了跑,代码很简单,以次博客记录一下,方便回顾 langchain LangChain 是一个基于大型语言模型(LLM)开发…...

VmWare Ubuntu22.04 搭建DPDK 20.11.1

一、开发环境 Ubuntu 版本 二、增加虚拟机的网卡 给虚拟机增加1个网卡,加上原来的网卡,一共2个 网络适配器作为 ssh 连接的网卡,网络适配器2作为 DPDK 运行的网卡。 三、NAT模式简介 这里待补充,网上都是那一张图,看不懂 四、使网卡名称从0开始命名 进入管理员权限 s…...

selenium-自动更新谷歌浏览器驱动

1、简介 selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题,因为有些网页数据是通过JavaScript动态加载的。selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如输入…...

34、协程

在Linux系统中,协程是一种轻量级的线程,它们允许在多个任务之间切换,而不需要操作系统的线程调度。协程可以分为有栈协程和无栈协程,以及对称协程和非对称协程。 有栈协程 有栈协程每个协程都有自己的栈空间,允许协程…...

Apache POI操作Excel详解

Maven依赖 <!-- 核心库&#xff08;支持.xls&#xff09; --> <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId> </dependency><!-- 支持.xlsx格式 --> <dependency><groupId>org.a…...

Docker容器部署elasticsearch8.*与Kibana8.*版本使用filebeat采集日志

第 1 步&#xff1a;使用 Docker Compose 部署 Elasticsearch 和 Kibana 首先&#xff0c;我们需要创建一个 docker-compose.yml 文件来定义和运行 Elasticsearch 和 Kibana 服务。这种方式可以轻松管理两个容器的配置和网络。 创建 docker-compose.yml 文件 在一个新的文件夹…...

OpenCV CUDA模块图像处理------双边滤波的GPU版本函数bilateralFilter()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数在 GPU 上执行双边滤波操作&#xff0c;是一种非线性平滑滤波器&#xff0c;能够在 保留边缘的同时去除噪声。 函数原型 void cv::cuda:…...

华为手机开机卡在Huawei界面不动怎么办?

遇到华为手机卡在启动界面&#xff08;如HUAWEI Logo界面&#xff09;的情况&#xff0c;可依次尝试以下解决方案&#xff0c;按操作复杂度和风险由低到高排序&#xff1a; &#x1f527; 一、强制重启&#xff08;优先尝试&#xff09; 1.通用方法‌ 长按 ‌电源键 音量下键‌…...

并行硬件环境及并行编程

文章目录 A1. (并行编程 基于的)硬件环境 的 基本模型A2. 特定的硬件实现B1. 并行编程基本模型与编程技术✅ 并行编程的一般流程**第一阶段&#xff1a;基于“编程直觉模型”设计程序****第二阶段&#xff1a;程序编译并部署到实际硬件** B2.特定的 硬件环境下的 并行编程 A1. …...

ORM框架(SQLAlchemy 与 Tortoise )

注&#xff1a;本文是python的学习笔记&#xff1b;不是教程&#xff01;不是教程&#xff01;内容可能有所疏漏&#xff0c;欢迎交流指正。 框架概述 什么是ORM&#xff1f; ORM&#xff08;Object-Relational Mapping&#xff0c;对象关系映射&#xff09;是一种编程技术&a…...

go语言map扩容

map是什么&#xff1f; ​在Go语言中&#xff0c;map是一种内置的无序key/value键值对的集合&#xff0c;可以根据key在O(1)的时间复杂度内取到value&#xff0c;有点类似于数组或者切片结构&#xff0c;可以把数组看作是一种特殊的map&#xff0c;数组的key为数组的下标&…...

安全访问家中 Linux 服务器的远程方案 —— 专为单用户场景设计

在现代远程办公与频繁差旅的背景下&#xff0c;许多人需要从外地访问家中的 Linux 文件服务器&#xff0c;以获取重要文件。在涉及敏感数据&#xff08;如客户资料、财务信息&#xff09;时&#xff0c;数据的安全性成为首要考虑因素。以下内容将聚焦于如何在仅有一台笔记本电脑…...

前端开发三剑客:HTML5+CSS3+ES6

在前端开发领域&#xff0c;HTML、CSS和JavaScript构成了构建网页与Web应用的核心基础。随着技术标准的不断演进&#xff0c;HTML5、CSS3以及ES6&#xff08;ECMAScript 2015及后续版本&#xff09;带来了诸多新特性与语法优化&#xff0c;极大地提升了开发效率和用户体验。本文…...

[Java 基础]Java 中的关键字

在 Java 编程语言中&#xff0c;关键字 (Keywords) 是预定义的、具有特殊含义的标识符 (identifiers)。它们是 Java 语言语法的一部分&#xff0c;被 Java 编译器赋予了特定的功能和用途。因此&#xff0c;你不能将关键字用作变量名、类名、方法名或其他用户自定义的标识符。 …...

5.3 Spring Boot整合JPA

本文详细介绍了如何在Spring Boot项目中整合Spring JPA&#xff0c;实现对数据库的高效操作。首先&#xff0c;创建Spring Boot项目并添加必要的依赖&#xff0c;如Druid数据源。接着&#xff0c;配置数据源属性&#xff0c;创建实体类Comment和Article&#xff0c;并使用JPA注…...

腾讯开源视频生成工具 HunyuanVideo-Avatar,上传一张图+一段音频,就能让图中的人物、动物甚至虚拟角色“活”过来,开口说话、唱歌、演相声!

腾讯混元团队提出的 HunyuanVideo-Avatar 是一个基于多模态扩散变换器&#xff08;MM-DiT&#xff09;的模型&#xff0c;能够生成动态、情绪可控和多角色对话视频。支持仅 10GB VRAM 的单 GPU运行&#xff0c;支持多种下游任务和应用。例如生成会说话的虚拟形象视频&#xff0…...

[文献阅读] Emo-VITS - An Emotion Speech Synthesis Method Based on VITS

[文献阅读]&#xff1a;An Emotion Speech Synthesis Method Based on VITS 在VITS基础上通过参考音频机制&#xff0c;获取情感信息&#xff0c;从而实现的情感TTS方式。 摘要 VITS是一种基于变分自编码器&#xff08;VAE&#xff09;和对抗神经网络&#xff08;GAN&#xf…...

网络协议通俗易懂详解指南

目录 1. 什么是网络协议? 1.1 协议的本质 1.2 为什么需要协议? 1.3 协议分层的概念 2. TCP协议详解 - 可靠的信使 📦 2.1 TCP是什么? 2.2 TCP的核心特性 🔗 面向连接 🛡️ 可靠传输 📊 流量控制 2.3 TCP三次握手 - 建立连接 2.4 TCP四次挥手 - 断开连接…...

OpenCV-Python Tutorial : A Candy from Official Main Page(持续更新)

OpenCV-Python 是计算机视觉领域最流行的开源库之一&#xff0c;它结合了 OpenCV (Open Source Computer Vision Library) 的 C 高性能实现和 Python 的简洁易用特性&#xff0c;为开发者提供了强大的图像和视频处理能力。具有以下优势&#xff1a; 典型应用领域&#xff1a; …...

【Vue】指令补充+样式绑定+计算属性+侦听器

【指令补充】 【指令修饰符】 指令修饰符可以让指令的 功能更强大&#xff0c;书写更便捷 分类&#xff1a; 1.按键修饰符&#xff08;侦测当前点击的是哪个按键&#xff09; 2.事件修饰符&#xff08;简化程序对于阻止冒泡&#xff0c; 一些标签的默认默认行为的操作&…...

.Net Framework 4/C# 泛型的使用、迭代器和分部类

一、泛型的使用 泛型是用于处理算法、数据结构的一种编程方法。泛型的目标是采用广泛适用和可交互性的形式来表示算法和数据结构,以便它们能够直接用于软件构造。 泛型简单理解就是,在声明时暂时不固定其类型,例如 int 类型、double 类型等,在调用泛型时,再将要用的类型补…...

LLM 笔记:Speculative Decoding 投机采样

1 基本介绍 投机采样&#xff08;Speculative Sampling&#xff09;是一种并行预测多个可能输出&#xff0c;然后快速验证并采纳正确部分的加速策略 在不牺牲输出质量的前提下&#xff0c;减少语言模型生成 token 所需的时间 传统的语言模型生成是 串行 的 必须生成一个&…...

当SAP系统内计划订单转换为生产订单时发生了什么?

【SAP系统研究】 #SAP #计划订单 #生产订单 #采购申请 一、关于计划订单的一点疑惑 曾经对SAP为什么会有计划订单,是感到很疑惑的。 这个界面简单,配置点也不多,能被随意“摆布”,一旦要变形就消失得无影无踪的计划订单,why? 但是,再次重新审视过之后,才发现它其实…...

PDF转PPT转换方法总结

你是否遇到过这些场景&#xff1f; 收到客户发来的产品手册PDF&#xff0c;明天就要用它做演示&#xff1b; 公司历史资料只有PDF版&#xff0c;领导突然要求更新为幻灯片。 这时PDF转PPT工具就成了救命稻草。接下来&#xff0c;介绍三种PDF转PPT工具。 1. iLoveOFD在线转换…...

3D Web轻量化引擎HOOPS Communicator的定制化能力全面解析

HOOPS Communicator 是Tech Soft 3D推出的高性能Web工程图形引擎。它通过功能丰富的JavaScript API&#xff0c;帮助开发团队在浏览器中快速添加2D/3D CAD模型的查看与交互功能。该引擎专为工程应用优化&#xff0c;支持大规模模型的流畅浏览、复杂装配的智能导航、流式加载和服…...

【力扣链表篇】19.删除链表的倒数第N个节点

题目&#xff1a; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1a;[]…...

.Net Framework 4/C# 集合和索引器

一、ArrayList 类&#xff08;集合&#xff09; ArrayList 类位于 System.Collections 命名空间下&#xff0c;它可以动态地添加和删除元素。 ArrayList 提供了3个构造器&#xff0c;通过这3个构造器可以有3种声明方式&#xff1a; 默认构造器&#xff0c;将会以默认&#xff…...