【Linux系统内核探索】进程调度

在这里插入图片描述

文章目录

  • 进程调度
    • 什么是进程调度?
    • 进程调度算法
    • task_struct的链式结构
  • 总结

进程调度

什么是进程调度?

进程调度是操作系统内核的核心功能之一,负责在多个进程之间分配CPU时间,使得系统能够同时运行多个进程。因为计算机的CPU资源有限,操作系统需要决定在任何时刻哪个进程能够使用CPU执行任务,这个过程就是进程调度。
Linux进程调度经历了多个阶段的优化,目前主流的Linux内核使用的是完全公平调度器。CFS调度器的核心思想是通过精确计算每个进程的“虚拟运行时间”来决定调度的公平性。CFS调度器不会简单依赖于时间片,而是通过调度树来快速查找下一个应运行的进程。
现代的Linux调度主要依赖于Linux的CFS调度器,在2.6版本之前主要用的是Linux内核O(1)调度算法,这次我们的重点在于Linux内核O(1)调度算法。

进程调度算法

我们打开Linux内核源码版本是2.5.18,打开源码后搜索runqueue。

struct runqueue {spinlock_t lock;/** nr_running and cpu_load should be in the same cacheline because* remote CPUs use both these fields when doing load calculation.*/unsigned long nr_running;
#ifdef CONFIG_SMPunsigned long cpu_load[3];
#endifunsigned long long nr_switches;/** This is part of a global counter where only the total sum* over all CPUs matters. A task can increase this counter on* one CPU and if it got migrated afterwards it may decrease* it on another CPU. Always updated under the runqueue lock:*/unsigned long nr_uninterruptible;unsigned long expired_timestamp;unsigned long long timestamp_last_tick;task_t *curr, *idle;struct mm_struct *prev_mm;prio_array_t *active, *expired, arrays[2];int best_expired_prio;atomic_t nr_iowait;#ifdef CONFIG_SMPstruct sched_domain *sd;/* For active balancing */int active_balance;int push_cpu;task_t *migration_thread;struct list_head migration_queue;int cpu;
#endif#ifdef CONFIG_SCHEDSTATS/* latency stats */struct sched_info rq_sched_info;/* sys_sched_yield() stats */unsigned long yld_exp_empty;unsigned long yld_act_empty;unsigned long yld_both_empty;unsigned long yld_cnt;/* schedule() stats */unsigned long sched_switch;unsigned long sched_cnt;unsigned long sched_goidle;/* try_to_wake_up() stats */unsigned long ttwu_cnt;unsigned long ttwu_local;
#endif
};

这次我们关注的主要属性是:active,expired,arrays
这结果属性分别是:

  1. active:表示活跃进程。
  2. expired:表示过期进程。
  3. arrays:表示一个结构体数组,活跃进程指向数组的第一个元素,过期进程指向数组的第二个元素。
    在这里插入图片描述这里我们只讨论后四十个,因为前面100个是实时进程。

简化过后我们就得到了一个非常简洁的结构体:
这里我们用queue来简化前面的类型

struct runqueue
{struct queue* active;struct queue* expired;struct queue arrays[2];
}

接下来我们进一步来讨论结构体queue:

struct prio_array {unsigned int nr_active;unsigned long bitmap[BITMAP_SIZE];struct list_head queue[MAX_PRIO];
};

上面是Linux内核源码
nr_active表示的是当前运行runqueue中的有效进程的数量。
queue表示一个队列,这个队列是一个链表的队列
在这里插入图片描述

bit_map表示位图,因为每次,我们根据优先级遍历的时候都需要从前面到后面一次遍历,这样时间复杂度来到了O(N),如果我们引入了位图的话,如果这个位上有进程挂着,那么对应比特位就应该被标记为1,如果这个点queue对应的位置没有一个进程,那么就用0来表示,在查找的时候我们就可以进行下面循环了:

for(int i=0;i<5;i++)
{if(bit_map[i]==0)continue;else //bit_map[i]!=0表示对应的32个比特位上对应的位子上有进程
}

原本O(N)的算法,运用位图之后,将时间复杂度缩减为了常数级别,因为,我们每次查找都是以32为单位,如果这32个bit位没有一个1我们可以直接跳到下面32个比特位上。
为什么这里是5个?

因为对应的队列就只有160空间,5*32恰好为160,所以这里开辟5个刚好合适。

接下来我们就来具体画一下这个结构的简图:
我们将前面100个位置给省略了,因为前面一百个空间是事实进程。
在这里插入图片描述
大致的简图就是上面这幅图,active指针指向的是arrays[0],expired指针指向的是arrays[1]。
CPU在调度的时候一般只会在active中调度,在调度中有三种情况:

  1. 进程退出
  2. 不退出,进程时间片到了
  3. 有新建进程产生

我们先来看第三种:有新进程产生,假设这个新进程的优先级很高,而且有很多新进程,比如说新进程的优先级是80,那么不断有新进程产生,那么是不是后面优先级低的是不是迟迟调度不到。
还有一种情况是不退出时间片到了的情况,如果时间片到了,我们就直接将这个进程插入到这个位置的队尾,那么这个位置调度完一轮回之后又来到了这个进程,那么还是迟迟调度不到后面的优先级的进程。

所以这里就产生了两个问题:

  1. 优先级高的,就表示就一定要优先吗?
  2. 优先级低的,就表示就一直不回被调度吗?
    这是一个饥饿问题,为了解决这个问题,我们引入了expired这个数组,为的就是让调度公平,当调度完一个进程之后,这个进程不会直接回到队列的尾部,因为后面的进程就不会被调度,所以刚调度完的进程会直接来到expired中,active永远都是一个存量进程的情况,还有创建的新的进程,也不会直接到active中,创建的新的队列还是会直接来到expired当中,当active中的进程调度完之后,只需要进行一步操作即可。
swap(&active,&expired)

只需要将两个队列交换即可,所以何时交换?就由nr_active控制,当active中的没有任何有效进程的时候,就将expired和active直接交换。
swap之前:按照优先级调度
swap之后,给了其他优先级的进程调度机会。
这样就实现了Linux内核O(1)调度算法。

task_struct的链式结构

接下来讨论完调度算法之后我们来讨论一下每个进程之间到底是如何连接起来的,我们知道task_struct是以链式结构来完成的。
Linux中的task_struct是用双线链表来连接的。
我们熟知的链式结构就是:

struct node
{type Data;struct node* next;struct node* prev;
}

但是这里Linux内核中的链式结构不是这样的,他只有连接关系,没有属性,我们来看看原码:
在这里插入图片描述

可以看见确实是这样的,说明task_struct的结构是这样的:
在这里插入图片描述内部套了一层双链表的数据结构,然后把数据属性放在外面。
在写代码的过程中,我们知道,我们一般都是用外层的结构体来访问内层的成员,但是在这里,我们只知道成员,我们该如何访问其他数据呢,在C语言阶段,我们知道结构体的存储是有偏移的。
我们假设有下面一个结构体:

struct A
{int a;char b;double c;float d;
}

上面这个结构体存储的时候大概是下面的简图:
在这里插入图片描述
假设我们有一个结构体:struct A obj
& o b j = & o b j → a \&obj=\&obj\rightarrow a &obj=&obja
从上面这个我们可以得知求出a的地址就可以求出整个结构体的地址。
利用这个公式: ( s t r u c t A ∗ ) ( & c − 偏移量 ) → 成员变量 (struct\ A*)(\&c-偏移量)\rightarrow成员变量 (struct A)(&c偏移量)成员变量
结构体的地址等于成员变量的地址减去对应的偏移量,最后就可以结构体的地址了。那么问题又来了,偏移量该怎么求,利用下面公式求出偏移量: & ( s t r u c t A ∗ ) 0 − > c \&(struct\ A*)0->c &(struct A)0>c 这样求出的地址就是相当于0位置的地址,再用c的地址减去即可,最后强转为 s t r u c t A ∗ struct\ A* struct A的类型。
在这里插入图片描述
在这里插入图片描述
task_struct内部的属性就是这样找到的。

总结

通过本篇博客的介绍,我们深入了解了Linux内核中的进程调度机制。进程调度作为操作系统的核心功能之一,决定了系统的响应速度和整体性能表现。不同的调度算法在特定场景下展现出了各自的优势,比如时间共享调度适用于多任务环境,而实时调度则更关注任务的及时性。掌握这些调度原理不仅能帮助我们更好地理解操作系统的工作方式,还能为优化系统性能、开发高效的应用程序提供有力的支持。在未来的学习中,进一步探索内核的其他模块将帮助我们更全面地掌握Linux系统的复杂性与强大之处。

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

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

相关文章

MongoDB的基本操作

&#x1f337;数据库准备 &#x1f388;Mongoshell 1.在指定目录下创建mongodb文件夹、其子文件log和data以及mongodb.log cd /home/ubuntu mkdir -p mongodb/data mkdir -p mongodb/log touch mongodb/log/mongodb.log 执行mongodb命令启动mongdb服务 mongod --dbpath /h…

SwiftUI:单个App支持设置多语言

SwiftUI 全新多语言方案 简化本地化的字符串- WWDC21 - 视频 本地化您的SwiftUI app - WWDC21 - 视频 构建全球化App&#xff1a;本地化的示例- WWDC22 - 视频 构建支持多语言的App - WWDC24 - 视频 单个App支持设置多语言 工程 Info.plist里添加 键值UIPrefersShowingLangua…

DDD重构-实体与限界上下文重构

DDD重构-实体与限界上下文重构 概述 DDD 方法需要不同类型的类元素&#xff0c;例如实体或值对象&#xff0c;并且几乎所有这些类元素都可以看作是常规的 Java 类。它们的总体结构是 Name: 类的唯一名称 Properties&#xff1a;属性 Methods: 控制变量的变化和添加行为 一…

大数据Azkaban(二):Azkaban简单介绍

文章目录 Azkaban简单介绍 一、Azkaban特点 二、Azkaban组成结构 三、Azkaban部署模式 1、solo-server ode&#xff08;独立服务器模式&#xff09; 2、two server mode&#xff08;双服务器模式&#xff09; 3、distributed multiple-executor mode&#xff08;分布式多…

Threejs 实现3D 地图(01)创建基本场景

"d3": "^7.9.0", "three": "^0.169.0", "vue": "^3.5.10" <script setup> import { onMounted,ref } from vue import * as THREE from three import * as d3 from "d3"; //莫开托坐标 矫正地图…

Vertx实现一个通用的MqttServer

mqtt协议介绍 简介 MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传输协议&#xff09;&#xff0c;是一种基于发布/订阅范式的“轻量级”消息协议&#xff0c;由 IBM 发布。 IoT 设备要运作&#xff0c;就必须连接到互联网&#xff0c;设备才…

数据分析-Apache_hive

任务一 创建库及外部表 在 comm 数 据 库 下 创 建 一 个 名 为 dws_behavior_log的外部表&#xff0c;如果表已存在&#xff0c;则先删除&#xff1b;分 区字段为dt&#xff0c;即根据日期进行分区&#xff1b;另外&#xff0c;要求指定表的存 储路径为HDFS的/behavior/dws/d…

java让系统直接播放音频/java获取音频流输送到播放设备SourceDataLine

Java Sound API支持常见的格式&#xff1a; WAV&#xff08;Waveform Audio File Format&#xff09; 常见的无损音频格式&#xff0c;支持 PCM&#xff08;脉冲编码调制&#xff09;编码。 AIFF&#xff08;Audio Interchange File Format&#xff09; 主要用于 Macintosh 系统…

OpenCV视觉分析之运动分析(2)背景减除类:BackgroundSubtractorKNN的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 K-最近邻&#xff08;K-nearest neighbours, KNN&#xff09;基于的背景/前景分割算法。 该类实现了如 319中所述的 K-最近邻背景减除。如果前景…

058_基于python时尚女装抖音号评论数据分析系统

目录 系统展示 开发背景 代码实现 项目案例 获取源码 博主介绍&#xff1a;CodeMentor毕业设计领航者、全网关注者30W群落&#xff0c;InfoQ特邀专栏作家、技术博客领航者、InfoQ新星培育计划导师、Web开发领域杰出贡献者&#xff0c;博客领航之星、开发者头条/腾讯云/AW…

智慧城管综合管理系统源码,微服务架构,基于springboot、vue+element+uniapp技术开发,支持二次开发

智慧城管源码&#xff0c;智慧城管执法办案系统源码 智慧城管综合执法办案平台是智慧城市框架下&#xff0c;依托物联网、云计算、多网融合等现代化技术&#xff0c;运用数字基础资源、多维信息感知、协同工作处置、智能化辅助决策分析等手段&#xff0c;形成具备高度感知、互联…

C++共同体

共同体是一种数据格式&#xff0c;他能储存不同的数据类型&#xff0c;但是同一时间只能储存其中的一种类型。 语法&#xff1a; union 共同体名 { 成员一的数据类型 成员名一&#xff1b; 成员二的数据类型 成员名二&#xff1b; 成员n的数据类型 成员名n&#xff1b; }

目标检测算法-YOLOV11解析

原文首发于微信公众号 微信公众号-人工智能与图像处理&#xff1a;目标检测算法-YOLOV11解析 一&#xff0c;YOLOV11概述 YOLOv11是由Ultralytics公司开发的新一代目标检测算法&#xff0c;它在之前YOLO版本的基础上进行了显著的架构和训练方法改进。整合了改进的模型结构设计…

Redis Search系列 - 第四讲 支持中文

目录 一、支持中文二、自定义中文词典2.1 Redis Search设置FRISOINI参数2.2 friso.ini文件相关配置1&#xff09;自定义friso UTF-8字典2&#xff09;修改friso.ini配置文件 三、实测中文分词效果 一、支持中文 Redis Stack 从版本 0.99.0 开始支持中文文档的添加和分词。中文…

Django+Vue智慧分析居家养老系统统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 需要的环境3.2 Django接口层3.3 实体类3.4 config.ini3.5 启动类3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质创作者&…

【学习笔记】强化学习

李宏毅深度强化学习 笔记 课程主页&#xff1a;NTU-MLDS18 视频&#xff1a;youtube B站 参考资料&#xff1a; 作业代码参考 纯numpy实现非Deep的RL算法 OpenAI tutorial 文章目录 李宏毅深度强化学习 笔记1. Introduction2. Policy Gradient2.1 Origin Policy Gradient2.2…

基于大型语言模型的智能网页抓取

Google Gemini 是 Google AI 创建的大型语言模型 (LLM) 系列&#xff0c;可提供最先进的 AI 功能。Gemini 模型包括&#xff1a; Gemini Ultra — 最大、最强大的模型&#xff0c;擅长处理编码、逻辑推理和创意协作等复杂任务。可通过 Gemini Advanced&#xff08;原名 Bard&a…

【Linux】基础IO-上

1、共识原理 1、文件 内容 属性 2、文件分为打开的文件和没打开的文件 3、打开的文件是谁打开的&#xff1f; 答案是&#xff1a;进程&#xff01;---本质是研究进程和文件的关系 文件被打开必须先被加载到内存&#xff0c;一个进程可以打开多个文件。因此&#xff0c;在OS内…

NVR小程序接入平台/设备EasyNVR多个NVR同时管理的高效解决方案

在当今的数字化安防时代&#xff0c;视频监控系统的需求日益复杂和多样化。为了满足不同场景下的监控需求&#xff0c;一种高效、灵活且兼容性强的安防视频监控平台——NVR批量管理软件/平台EasyNVR应运而生。本篇探讨这一融合所带来的创新与发展。 一、NVR监测软件/设备EasyNV…

mysql 13 MySQL基于规则的优化

01.条件化简 我们编写的查询语句的搜索条件本质上是一个表达式&#xff0c;这些表达式可能比较繁杂&#xff0c;或者不能高效的执行&#xff0c; MySQL的查询优化器会为我们简化这些表达式。为了方便大家理解&#xff0c;我们后边举例子的时候都使用诸如 a 、 b 、 c 之类的简…