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

Linux内核--进程管理(十三)O(1)调度算法

目录

一、引言
二、O(1)调度算法原理
------>2.1、prio_array 结构
------>2.2、runqueue 结构
三、实时进程调度
四、普通进程调度
------>4.1、运行时间片计算
五、O(1)调度算法实现
------>5.1、时钟中断任务调度
------>5.2、任务调度

一、引言

Linux是一个支持多任务的操作系统,而多个任务之间的切换是通过 调度器 来完成,调度器 使用不同的调度算法会有不同的效果。Linux2.4版本使用的调度算法的时间复杂度为O(n),其主要原理是通过轮询所有可运行任务列表,然后挑选一个最合适的任务运行,所以其时间复杂度与可运行任务队列的长度成正比。而Linux2.6开始替换成名为 O(1)调度算法,顾名思义,其时间复杂度为O(1)。虽然在后面的版本开始使用 CFS调度算法(完全公平调度算法),但了解 O(1)调度算法 对学习Linux调度器还是有很大帮助的,所以本文主要介绍 O(1)调度算法 的原理与实现。

二、O(1)调度算法原理

2.1、prio_array 结构

O(1)调度算法 通过优先级来对任务进行分组,可分为140个优先级(0 ~ 139,数值越小优先级越高),每个优先级的任务由一个队列来维护。
prio_array 结构就是用来维护这些任务队列,如下代码:

#define MAX_USER_RT_PRIO    100
#define MAX_RT_PRIO         MAX_USER_RT_PRIO
#define MAX_PRIO            (MAX_RT_PRIO + 40)#define BITMAP_SIZE ((((MAX_PRIO+1+7)/8)+sizeof(long)-1)/sizeof(long))struct prio_array {int nr_active;unsigned long bitmap[BITMAP_SIZE];struct list_head queue[MAX_PRIO];
};

下面介绍 prio_array 结构各个字段的作用:

  1. nr_active: 所有优先级队列中的总任务数。
  2. bitmap: 位图,每个位对应一个优先级的任务队列,用于记录哪个任务队列不为空,能通过 bitmap 够快速找到不为空的任务队列。
  3. queue: 优先级队列数组,每个元素维护一个优先级队列,比如索引为0的元素维护着优先级为0的任务队列。

下图更直观地展示了 prio_array 结构各个字段的关系:
在这里插入图片描述
如上图所述,bitmap 的第2位和第6位为1(红色代表为1,白色代表为0),表示优先级为2和6的任务队列不为空,也就是说 queue 数组的第2个元素和第6个元素的队列不为空。

2.2、runqueue 结构

另外,为了减少多核CPU之间的竞争,所以每个CPU都需要维护一份本地的优先队列。因为如果使用全局的优先队列,那么多核CPU就需要对全局优先队列进行上锁,从而导致性能下降。

每个CPU都需要维护一个 runqueue 结构,runqueue 结构主要维护任务调度相关的信息,比如优先队列、调度次数、CPU负载信息等。其定义如下:

struct runqueue {spinlock_t lock;unsigned long nr_running,nr_switches,expired_timestamp,nr_uninterruptible;task_t *curr, *idle;struct mm_struct *prev_mm;prio_array_t *active, *expired, arrays[2];int prev_cpu_load[NR_CPUS];task_t *migration_thread;struct list_head migration_queue;atomic_t nr_iowait;
};

runqueue 结构有两个重要的字段:active 和 expired,这两个字段在 O(1)调度算法 中起着至关重要的作用。我们先来了解一下 O(1)调度算法 的大概原理。

我们注意到 active 和 expired 字段的类型为 prio_array,指向任务优先队列。active 代表可以调度的任务队列,而 expired 字段代表时间片已经用完的任务队列。active 和 expired 会进行以下两个过程:

  1. 当 active 中的任务时间片用完,那么就会被移动到 expired 中。
  2. 当 active 中已经没有任务可以运行,就把 expired 与 active 交换,从而 expired 中的任务可以重新被调度。

如下图所示:
在这里插入图片描述
在这里插入图片描述

二、实时进程调度

实时进程分为 FIFO(先进先出) 和 RR(时间轮询) 两种,其调度算法比较简单,如下:

  1. 先进先出的实时进程调度:如果调度器在执行某个先进先出的实时进程,那么调度器会一直运行这个进程,直至其主动放弃运行权(退出进程或者sleep等)。
  2. 时间轮询的实时进程调度:如果调度器在执行某个时间轮询的实时进程,那么调度器会判断当前进程的时间片是否用完,如果用完的话,那么重新分配时间片给它,并且重新放置回 active 队列中,然后调度到其他同优先级或者优先级更高的实时进程进行运行。

三、普通进程调度

每个进程都要一个动态优先级和静态优先级,静态优先级不会变化(进程创建时被设置),而动态优先级会随着进程的睡眠时间而发生变化。动态优先级可以通过以下公式进行计算:

动态优先级 = max(100, min(静态优先级 – bonus + 5), 139))

上面公式的 bonus(奖励或惩罚) 是通过进程的睡眠时间计算出来,进程的睡眠时间越大,bonus 的值就越大,那么动态优先级就越高(前面说过优先级的值越小,优先级越高)。

另外要说明一下,实时进程的动态优先级与静态优先级相同。

当一个普通进程被添加到运行队列时,会先计算其动态优先级,然后按照动态优先级的值来添加到对应优先级的队列中。而调度器调度进程时,会先选择优先级最高的任务队列中的进程进行调度运行。

3.1、运行时间片计算

当进程的时间用完后,就需要重新进行计算。进程的运行时间片与静态优先级有关,可以通过以下公式进行计算:

静态优先级 < 120,运行时间片 = max((140-静态优先级)*20, MIN_TIMESLICE)
静态优先级 >= 120,运行时间片 = max((140-静态优先级)*5, MIN_TIMESLICE)

四、O(1)调度算法实现

接下来我们分析一下 O(1)调度算法 在内核中的实现。

4.1、时钟中断

时钟中断是由硬件触发的,可以通过编程来设置其频率,Linux内核一般设置为每秒产生100 ~ 1000次。时钟中断会触发调用 scheduler_tick() 内核函数,其主要工作是:减少进程的可运行时间片,如果时间片用完,那么把进程从 active 队列移动到 expired 队列中。代码如下:

void scheduler_tick(int user_ticks, int sys_ticks)
{runqueue_t *rq = this_rq();task_t *p = current;...// 处理普通进程if (!--p->time_slice) {                // 减少时间片, 如果时间片用完dequeue_task(p, rq->active);       // 把进程从运行队列中删除set_tsk_need_resched(p);           // 设置要重新调度标志p->prio = effective_prio(p);       // 重新计算动态优先级p->time_slice = task_timeslice(p); // 重新计算时间片p->first_time_slice = 0;if (!rq->expired_timestamp)rq->expired_timestamp = jiffies;// 如果不是交互进程或者没有出来饥饿状态if (!TASK_INTERACTIVE(p) || EXPIRED_STARVING(rq)) {enqueue_task(p, rq->expired); // 移动到expired队列} elseenqueue_task(p, rq->active);  // 重新放置到active队列}...
}

上面代码主要完成以下几个工作:

  1. 减少进程的时间片,并且判断时间片是否已经使用完。
  2. 如果时间片使用完,那么把进程从 active 队列中删除。
  3. 调用 set_tsk_need_resched() 函数设 TIF_NEED_RESCHED 标志,表示当前进程需要重新调度。
  4. 调用 effective_prio() 函数重新计算进程的动态优先级。
  5. 调用 task_timeslice() 函数重新计算进程的可运行时间片。
  6. 如果当前进程是交互进程或者出来饥饿状态,那么重新加入到 active 队列。
  7. 否则把今天移动到 expired 队列。
4.2、任务调度

如果进程设置了 TIF_NEED_RESCHED 标志,那么当从时钟中断返回到用户空间时,会调用 schedule() 函数进行任务调度。
schedule() 函数代码如下:

void schedule(void)
{...prev = current;  // 当前需要被调度的进程rq = this_rq();  // 获取当前CPU的runqueuearray = rq->active; // active队列// 如果active队列中没有进程, 那么替换成expired队列if (unlikely(!array->nr_active)) {rq->active = rq->expired;rq->expired = array;array = rq->active;rq->expired_timestamp = 0;}idx = sched_find_first_bit(array->bitmap); // 找到最高优先级的任务队列queue = array->queue + idx;next = list_entry(queue->next, task_t, run_list); // 获取到下一个将要运行的进程...prev->sleep_avg -= run_time; // 减少当前进程的睡眠时间...if (likely(prev != next)) {...prev = context_switch(rq, prev, next); // 切换到next进程进行运行...}...
}

上面代码主要完成以下几个步骤:

  1. 如果当前 runqueue 的 active 队列为空,那么把 active 队列与 expired 队列进行交换。
  2. 调用 sched_find_first_bit() 函数在 bitmap 中找到优先级最高并且不为空的任务队列索引。
  3. 减少当前进程的睡眠时间。
  4. 调用 context_switch() 函数切换到next进程进行运行。

相关文章:

Linux内核--进程管理(十三)O(1)调度算法

目录 一、引言 二、O(1)调度算法原理 ------>2.1、prio_array 结构 ------>2.2、runqueue 结构 三、实时进程调度 四、普通进程调度 ------>4.1、运行时间片计算 五、O(1)调度算法实现 ------>5.1、时钟中断任务调度 ------>5.2、任务调度 一、引言 …...

【QT】发生的运行时错误汇总

1 、QObject::startTimer: Timers cannot be started from another thread 错误原因&#xff1a;QObject是可重入的&#xff0c;它的大多数非GUI子类&#xff0c;例如QTimer, QTcpSocket, QUdpSocket and QProcess都是可重入的&#xff0c;使得这些类可以同时用于多线程。需要…...

机器学习常用算法模型总结

文章目录 1.基础篇&#xff1a;了解机器学习1.1 什么是机器学习1.2 机器学习的场景1.2.1 模式识别1.2.2 数据挖掘1.2.3 统计学习1.2.4 自然语言处理1.2.5 计算机视觉1.2.6 语音识别 1.3 机器学习与深度学习1.4 机器学习和人工智能1.5 机器学习的数学基础特征值和特征向量的定义…...

笔记中所得(已删减)

1.交流电的一个周期内电压/电流的平均值都为0 2.电动势:电池将单位正电荷由负极搬到正极所做的功 5.额定能量:电池的额定容量乘以标称电压,以Wh为单位 6.500mAh意义是可以以500mA的电流放电1小时 7.电池容量的单位是mAh 13.实际电流源不能串联 14. 15. 16. 17. 18. 19.电…...

在Django5中使用Websocket进行通信

Docker安装Redis docker run --restartalways -p 6379:6379 --name redis -d redis:7.0.12 --requirepass zhangdapeng520安装依赖 参考文档&#xff1a;https://channels.readthedocs.io/en/latest/installation.html pip install "channels[daphne]"展示聊天页…...

外汇天眼:CySEC与NAGA Markets Europe达成15万欧元的和解

塞浦路斯证券交易委员会&#xff08;CySEC&#xff09;已经与NAGA Markets Europe达成15万欧元的和解。有关监管决定的会议于2023年3月举行&#xff0c;然而直到今天才公布这个决定。 该和解符合2009年塞浦路斯证券交易委员会法第37(4)条的规定&#xff0c;该条赋予CySEC就任何…...

Docker仓库搭建与镜像推送拉取

1.Docker镜像仓库 搭建镜像仓库可以基于Docker官方提供的DockerRegistry来实现。 官网地址&#xff1a;https://hub.docker.com/_/registry 1.1.简化版镜像仓库 Docker官方的Docker Registry是一个基础版本的Docker镜像仓库&#xff0c;具备仓库管理的完整功能&#xff0c;…...

最适合初学者的PHP集成环境!

如果你是一个php初学者&#xff0c;千万不要为了php的运行环境去浪费时间&#xff0c;这里我给大家推荐一款php的集成环境&#xff1a;phpStudy。它具备了php运行的三要素&#xff1a;php、apache、mysql&#xff0c;当然它具备的功能远不止这些。 phpstudy V8安装步骤 步骤一…...

添加 Android App Links

添加 Android App Links功能 介绍一个简单的效果Android配置Add Url intent filtersAdd logic to handle the intentAssociate website 搭建网页支持AppLinks 介绍 Android App Links 是指将用户直接转到 Android 应用内特定内容的 HTTP 网址。Android App Links 可为您的应用带…...

五、Spring AOP面向切面编程(基于注解方式实现和细节)

本章概要 Spring AOP底层技术组成初步实现获取通知细节信息切点表达式语法重用&#xff08;提取&#xff09;切点表达式环绕通知切面优先级设置CGLib动态代理生效注解实现小结 5.5.1 Spring AOP 底层技术组成 动态代理&#xff08;InvocationHandler&#xff09;&#xff1a;…...

ES6 class详解

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…...

嵌入式固件加密的几种方式

一、利用id做软件加密 1&#xff0c;如果板子上有外部存储器&#xff0c;可以先编写一个程序&#xff0c;利用算法把id计算得到一些值存入外部存储器&#xff0c;然后再烧写真正的程序&#xff0c;真正的程序去校验外部存储器的数据是否合法即可 2&#xff0c;利用板子上按键组…...

[C#]使用onnxruntime部署Detic检测2万1千种类别的物体

【源码地址】 github地址&#xff1a;https://github.com/facebookresearch/Detic/tree/main 【算法介绍】 Detic论文&#xff1a;https://arxiv.org/abs/2201.02605v3 项目源码&#xff1a;https://github.com/facebookresearch/Detic 在Detic论文中&#xff0c;Detic提到…...

关于Spring @Transactional事务传播机制详解

Spring事务传播机制 1.什么是事务传播机制&#xff1f;2.Spring事务传播类型Propagation介绍3.具体案例总结 Spring事务传播机制 1.什么是事务传播机制&#xff1f; 举个栗子&#xff0c;方法A是一个事务的方法&#xff0c;方法A执行过程中调用了方法B&#xff0c;那么方法B有…...

力扣139.单词拆分

思路&#xff1a;动态规划&#xff0c;设dp[]记录当前字符能不能通过字典里的单词到达&#xff0c;双层循环&#xff0c;外层循环遍历字符串每一个字符&#xff0c;内层遍历当前i字符之前的所有以i字符结尾的子串 例如字符串&#xff1a;leetcode i遍历到了t 那么内层循环就…...

Docker 镜像命令总汇

目录 1、查看镜像列表 2、搜索镜像 3、拉取镜像 4、删除镜像 5、显示镜像详细信息 6、显示镜像历史 7、导出镜像 8、导入镜像 9、清理未使用的镜像 10、强制删除镜像 1、查看镜像列表 docker images 这个命令列出了你系统中的所有 Docker 镜像&#xff0c;包括镜像名…...

客户服务:助力企业抵御经济衰退的关键要素与策略

目前经济仍悬而未决是否陷入衰退。当前情况下&#xff0c;尽管通胀率高企&#xff0c;消费者支出良好&#xff0c;就业率也在上升&#xff0c;表明就业市场强劲。然而&#xff0c;有人认为衰退可能会在2024年第一季度发生。经济环境的不确定性可能会让人望而却步&#xff0c;但…...

第八周:AIPM面试准备

以下为从开始准备转行到拿到offer期间每天需要准备的10个面试题目以及相关知识补充&#xff01;来源广泛&#xff0c;从各个地方收集&#xff0c;只提供题目&#xff0c;我自己的尝试回答也会陆续放在我的喜马拉雅&#xff0c;基于我粗浅的认知&#xff0c;分享我粗浅的作答思路…...

阿里云2核2G3M服务器能放几个网站?有限制吗?

阿里云2核2g3m服务器可以放几个网站&#xff1f;12个网站&#xff0c;阿里云服务器网的2核2G服务器上安装了12个网站&#xff0c;甚至还可以更多&#xff0c;具体放几个网站取决于网站的访客数量&#xff0c;像阿里云服务器网aliyunfuwuqi.com小编的网站日访问量都很少&#xf…...

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK设置相机本身的数据保存(CustomData)功能(C#)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK设置相机本身的数据保存&#xff08;CustomData&#xff09;功能&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机的数据保存&#xff08;CustomData&#xff09;功能的技术背景CameraExplorer如何使用图像剪切&#xff…...

从零开始配置kali2023环境:镜像保存和导入

对原始的镜像做了一些改动&#xff0c;然后把当前容器状态打包为新的镜像&#xff0c;这样以后可以部署到其他地方了&#xff0c;而不用再安装软件等改动等等 1.查看容器id ┌──(holyeyes㉿kali2023)-[~] └─$ sudo docker ps ┌──(holyeyes㉿kali2023)-[~] └─$ s…...

Transformer梳理与总结

其实transformer的成功也是源于对注意力机制的应用&#xff0c;其本质上还是可以归因于注意力机制&#xff0c;首先我们先来了解一下什么是注意力机制。在注意力机制的背景下&#xff0c;自主性提示被称为查询&#xff08;query&#xff09;,给定任何查询&#xff0c;注意力机制…...

php之 校验多个时间段是否重复

参考网址 https://www.kancloud.cn/xiaobaoxuetp/mywork/3069416 https://segmentfault.com/a/1190000020487996 PHP判断多个时间段是否存在跨天或重复叠加的场景 /*** PHP计算两个时间段是否有交集&#xff08;边界重叠不算&#xff09;** param string $beginTime1 开始时间…...

atoi函数的模拟实现

这里强力推荐一篇文章 http://t.csdnimg.cn/kWuAm 详细解析了atoi函数以及其模拟实现&#xff0c;我这里就不说了。 这里作者先把自己模拟的代码给大家看一下。 int add(char* arr) {char* arr2 arr;while (*arr!-48){arr;}arr--;int sum 0;int n 0;while (arr ! (arr2-…...

编程笔记 html5cssjs 009 HTML链接

编程笔记 html5&css&js 009 HTML链接 一、HTML 链接二、文本链接三、图片链接四、HTML 链接- id 属性五、锚点链接六、HTML 链接 - target 属性七、属性downloadhrefpingreferrerpolicyreltargettype 八、操作小结 网页有了链接&#xff0c;就可根据需要进行跳转。纸质…...

Vue实现导出Excel表格,提示“文件已损坏,无法打开”的解决方法

一、vue实现导出excel 1、前端实现 xlsx是一个用于读取、解析和写入Excel文件的JavaScript库。它提供了一系列的API来处理Excel文件。使用该库&#xff0c;你可以将数据转换为Excel文件并下载到本地。这种方法适用于在前端直接生成Excel文件的场景。 安装xlsx依赖 npm inst…...

分发糖果,Java经典算法编程实战。

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…...

鸿蒙原生应用再添新丁!中国移动 入局鸿蒙

鸿蒙原生应用再添新丁&#xff01;中国移动 入局鸿蒙 来自 HarmonyOS 微博1月2日消息&#xff0c;#中国移动APP启动鸿蒙原生应用开发#&#xff0c;拥有超3亿用户的中国移动APP宣布&#xff0c;正式基于HarmonyOS NEXT启动#鸿蒙原生应用#及元服务开发。#HarmonyOS#系统的分布式…...

一个人能不能快速搭建一套微服务环境

一、背景 大型软件系统的开发现在往往需要多人的协助&#xff0c;特别是前后端分离的情况下下&#xff0c;分工越来越细&#xff0c;那么一个人是否也能快速搭建一套微服务系统呢&#xff1f; 答案是能的。看我是怎么操作的吧。 二、搭建过程 1、首先需要一套逆向代码生成工…...

计算机毕业设计------经贸车协小程序

项目介绍 本项目分为三种用户类型&#xff0c;分别是租赁者&#xff0c;车主&#xff0c;管理员用户&#xff1b; 管理员用户包含以下功能&#xff1a; 管理员登录,个人中心,租赁者管理,车主管理,赛事活动管理,车类别管理,租车管理,租车订单管理,车辆出售管理,购买订单管理,…...

郑州做网站好/品牌宣传策划方案

1、在虚拟机上安装 linux 首先到官网上下载centos 点击找到get centos 或者 download等进入下载页面点击 DVD ISO 进入&#xff08;isoredirect.centos.org/centos/7/isos/x86_64/CentOS-7-x86_64-DVD-1611.iso&#xff09; 选择一个镜像文件下载&#xff0c;这里选择了163下载…...

兰州彩票网站制作/聊城网站seo

微信小程序 MD5的方法详解生成的文件可以放在 utils文件中哦&#xff01;&#xff01;&#xff01;/** A JavaScript implementation of the RSA Data Security, Inc. MD5 Message* Digest Algorithm, as defined in RFC 1321.* Version 1.1 Copyright (C) Paul Johnston 1999…...

网页设计作业样例/seo基础教程

光敏电阻器&#xff08;photoresistor&#xff09;又叫光感电阻&#xff0c;它的电阻值会根据光的强度变化而变化。 现在我要把它接入树莓派Pico&#xff0c;观察电阻值随光强度的变化情况&#xff0c;本试验参考的文章&#xff1a;https://peppe8o.com/how-to-use-a-photoresi…...

只做正品的购物网站/品牌营销经典案例

安装nodejs环境这个直接搜索安装即可&#xff0c;安装完成之后&#xff0c;通过如下命令检测环境变量是否安装成功&#xff1a;λ node -v# 输出版本号v12.13.1正确输入版本号即可。安装cnpmcnpm是淘宝镜像&#xff0c;可以加快依赖的安装速度npm install cnpm -g --registryht…...

wordpress tob8.0/谷歌sem推广

一 问题描述 问题描述前&#xff0c;请允许我&#xff0c;吐槽一下&#xff0c;这个问题困扰了一天&#xff0c;下面在业务层下的代码中&#xff0c;cache注解标注了value的名称&#xff0c;但是没有设置key&#xff0c;且传递的参数为 CrawlRecordParamVo crawlRecordParamV…...

如皋住房和城乡建设局网站/高端网站定制设计

2019独角兽企业重金招聘Python工程师标准>>> 使用react时,如果我们将层级划分的很清楚,那么就会经常出现子级组件更改父级组件状态的情况,而这种情况并不能单单由redux来解决,那么要怎么样方便快捷的实现这种需求呢? 其实说来也很容易, 简单地说就是在父级元素调用…...