Linux-进程调度器

news2024/11/15 10:28:09

1. 前言 

        在计算机中,进程的数量远多于cpu的数量,所以就存在,多个进程抢占一个cpu的情况,所以就需要一套规则,决定这些进程被处理的顺序,这就叫做进程调度。

        在我的简单理解下,其实就是把进程放在一个队列中,cpu挨个去执行,但是后面知道了进程具有并发性,其实就是,一个cpu在某一时刻,只能处理一个进程,但是cpu并不会处理完这个进程,而是处理很短的时间(毫秒级别), 进程在cpu上跑的时间段,我们称之为时间片。不论处理的怎么样,结束没结束不重要,接着处理下一个,这个进程中间的上下文数据被保存到进程PCB中,然后去排队吧。

5e0106a7c5b34d41b826fee154b7e028.png

        这就是并发,虽然在某一时刻,我只在处理一个任务,但是在一个时间段,我就相当于同时处理多个任务。这些任务是被同步推进的。

        后面还有进程优先级的概念,就相当于在排队,但是你VIP你就可以按照规则排在前面。

        但是对于cpu而言,他只是负责计算,至于这些进程的优先级处理我并不关心,我只想要知道下一个进程是谁。那进程排序的规则是什么,又是谁来维护呢?

2. 进程调度器

        进程调度器,它负责计算并决定一个进程何时获取CPU时间以及占用CPU的时长。

a74bb365b5b44fefaf7a5b9bc763cb7d.png

        不要害怕,这些是我总结的大部分内容的结构图 ,接下来我会一一介绍这些

        你应该看到了,进程调度器在最上面,和cpu交互的那个sched_class,Linux设计的一个结构体类型,里面定义了很多抽象的接口(函数指针)。

struct sched_class{
    // 链表
    const struct sched_class* next; 

    // 向运行队列添加一个进程
    void(*enqueue_task)(struct rq* rq, struct task_struct* p, int flags);

    // ...
    
    // 挑选下一个优先级更高的进程
    struct task_struct(*pick_next_task)(struct rq* rq, struct task_struct* prev, struct rq_flags* rf);
}

 enqueue_task:向运行队列中插入一个进程

 pick_next_task:从运行队列中挑选下一个优先级更高的进程

        里面类似的函数指针还有很多,实现不同的功能。其次调度器其实是一个链表。进程通用调度器提供了一个模板,调度类其实就是这些类型的实现,以及对这些接口的实现。

3. 进程调度类

        为什么要实现这么多的调度类呢,因为不同的使用场景:

  • stop调度类,是系统内核线程所使用,用户不能使用,优先级最高,任务一但被执行,它将不能被抢占,不能被切换,其将一直执行下去,直至进程执行完或主动让出cpu。         
  • 截止日期(dl)调度类,这个任务有最后期限,必须在任务最后期限之前完成,例如播放视频,一秒钟60帧的视频,大概每16毫秒就要播放一帧画面,这个就是最后期限
  • 实时(rt)调度类,需要立马执行的任务,需要具有实时的特性,就像驾驶系统的刹车任务,必须要实时响应
  • 完全公平(fair)调度类,这些任务都是完全公平的接受“相同”的时间,这个时间其实是虚拟时间,后面会说
  • 空闲(ide)调度类,没有其他进程需要执行,就轮到它了

        因为每个调度类都有自己的排序规则,所以Linux就使用这种设计:第一层,定义结构体类型,定义抽象的操作接口,比如向运行队列插入一个任务,从运行队列中挑选一个任务;第二层,调度类,根据自身类的特点,实现具体的操作。

         通过这样两层,调度器可以从每个调度类的细节实现中抽离出来

4. 进程运行队列

        运行队列,顾名思义,运行队列...

        调度类,是方法的实现,你需要插入任务啊,还是删除任务,还是选择任务,这些方法都可以通过调度类的函数方法实现,但是没有数据只有方法肯定是不行的。

        运行队列,其实就是对各个进程的通过数据结构管理起来,简而言之存放进程的地方

5cff9994499a4b16bd1d9ad1cfa2f8af.png

        不同的调度类,需要不同的数据结构来进行管理,所以就出现了不同的运行队列,例如实时调度类就要有先进先出队列,环形队列。截止日期调度类和完全公平调度类依赖的数据结构都是红黑树。 

5. 进程调度过程

        进程的调度是从调用通用调度器开始的,kernel/sched/core.c中定义的schedule()函数。该函数的功能是挑选下一个最佳的可运行任务。schedule()函数中的pick_next_task()遍历调度类中包含的所有对应的函数,并最终选出要运行的下一个最佳任务。        

---摘自《精通Linux内核开发》

c31f3b032dfa4a219c1c0fdd99af6013.png

        prev是一个task_struct*类型的指针,task_struct内部包含一个sched_class*类型的指针,指向该进程属于的调度类。 

6. CFS完全公平调度类(浅谈)

        CFS,这里主要谈谈以下三点:虚拟运行时间(vruntime),权重计算,红黑树排序

        前面两个主要是为了CFS的公平和优先级,最后一个决定运行队列的数据结构

        如何能够保证在这个类中的所有进程都是完全公平的接受cpu的调度呢,但是还有优先级。你一听,这不是互相矛盾嘛,又要公平,又要有优先级。确实矛盾。但是没办法,就是在有优先级的情况下实现公平。

        如果只要公平,那就每个进程都运行相同的时间,如果要优先级,那就你先我后,但是你忘记并发了嘛,必须要每一个进程都要上去跑一会。

        所以虚拟运行时间(vruntime)和权重计算就是这么来的。

        每一个进程都有一个真实运行时间和虚拟运行时间,真实运行时间,就是你真实在cpu上跑了多少毫秒,vruntime其实是根据真实运行时间和优先级权重的权重计算而来的,然后再红黑树中按照vruntime来进行排序。每次pick_next_task都会选择红黑树最左端的进程。

        nice值标识进程的优先级,nice值每减少1,CPU的时间片会增加10%

        例如:一个A进程nice值为0,另一个B进程nice值为1,假如A进程的时间片是10ms,它也真实跑了10ms,那么他的vruntime就会加10,而B进程时间片是11ms,它也真实跑了11ms,但是根据权重计算,它的vruntime只会加10.由此实现完全公平。

7. 实时调度类(浅谈)

        实时调度类,它的运行队列的数据结构是带头双向链表。

        它有两种调度策略:

SCHED_FIFO(先进先出实时调度策略)

        进程一旦获得CPU执行权,就会一直运行下去,直到该进程自愿放弃CPU,实时进程按照优先级队列排序

SCHED_RR(轮转实时调度策略)

        进程在执行完一个时间片后,即使没有完成任务,也会被迫让出CPU给同一优先级的其他进程,同一优先级的实时进程能够实现时间片的轮转,确保在紧迫性相同的情况下公平分配CPU时间

8. 总结

        Linux内核的知识非常多,对于进程调度这一块内容有很多,这篇博客只能带大家揭开内核神秘面纱的一角,希望大家有所收获。

        关于进程调度器的代码啊,我建议大家可以看看这篇博客:http://t.csdnimg.cn/ORcS7

完 

 

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

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

相关文章

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-6.4--汇编LED驱动程序

前言: 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM(MX6U)裸机篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

网络安全之弱口令与命令爆破(中篇)(技术进阶)

目录 一,什么是弱口令? 二,为什么会产生弱口令呢? 三,字典的生成 四,使用Burpsuite工具验证码爆破 总结 笔记改错 一,什么是弱口令? 弱口令就是容易被人们所能猜到的密码呗&a…

Android数据恢复软件快速比较:Android数据恢复的7最佳工具

您在 Android 设备上保留哪些类型的数据?如果您和大多数人一样,那么您可能已经列出了文档、照片、视频和音频文件。如果您使用智能手机或平板电脑的时间足够长,我们愿意打赌您拥有Android数据丢失的第一手经验。 幸运的是,我们也…

JSON教程(非常详细)

参考文章来源:JSON教程(非常详细) 目录 JSON JSON 发展史 为什么要使用 JSON? JSON 的不足 存储格式 使用场景 1) 定义接口 2) 序列化 3) 生成 Token 4) 配置文件 JSON语法规则 JSON 与 JavaScript 对象的区别 JSON数…

Python | Leetcode Python题解之第62题不同路径

题目: 题解: class Solution:def uniquePaths(self, m: int, n: int) -> int:return comb(m n - 2, n - 1)

基于SSM的个人博客系统(三)

目录 第五章 系统实现 5.1 登录模块 5.1.1 博主登录 5.2 博客管理模块: 5.2.1 博客查询 5.2.2 博客新建 5.2.3 博客修改 5.2.4 博客删除 5.3 博客类别管理模块 前面内容请移步 基于SSM的个人博客系统(二) 个人博客系统的设计…

飞腾FT1500A-16 6U VPX高性能密集计算刀片

飞腾FT1500A-16 6U VPX高性能密集计算刀片 一款高性能6U VPX单板显示计算机,产品遵循OpenVPX Vita65规范。采用目前主流的GPGPU架构,其板载一颗天津飞腾公司的FT1500A-4四核处理器,并搭配AMD?公司的高性能嵌入式显卡Radeon? E8860 GPU。E88…

【论文阅读:Data Shapley: Equitable Valuation of Data for Machine Learning】

1.基于蒙特卡罗方法和截断的方法计算(TMC—Shapley) 输入 训练数据集D学习算法A表现分V 输出 各方数据的贡献 ϕ i \phi_i ϕi​ 初始化 初始化各方的贡献 ϕ i 0 \phi_i0 ϕi​0,并设置当前迭代轮次为0 过程 算法进入一个循环迭代,直到满足…

Vue 之 在当前页面的实现分页效果

目录 场景实现 场景 假设,我们现在有这么一个需求: 上述图片的空白内容是活动的,由下面的两个按钮控制上一页、下一页;我们应该可以怎么去实现? 实现 思路: 其实这个问题,我们仿照其他的UI框…

ctf web-部分

** web基础知识 ** *一.反序列化 在PHP中,反序列化通常是指将序列化后的字节转换回原始的PHP对象或数据结构的过程。PHP中的序列化和反序列化通过serialize()和unserialize()函数实现。 1.序列化serialize() 序列化说通俗点就是把一个对象变成可以传输的字符串…

2024年五一数学建模C题完整解题思路代码

2024年第二十一届五一数学建模竞赛题目 C题 煤矿深部开采冲击地压危险预测 煤炭是中国的主要能源和重要的工业原料。然而,随着开采深度的增加,地应力增大,井下煤岩动力灾害风险越来越大,严重影响着煤矿的安全高效开采。在各类深…

如何快速搭建nginx服务

华子目录 nginx简介概念特点nginx框架nginx关键工作机制 nginx正向代理功能nginx反向代理功能nginx反向代理的工作流程代理本质 nginx负载均衡部署nginx常用命令systemctl系列nginx自带命令 nginx配置文件主配置文件/etc/nginx/nginx.conf内容结构模块分析配置分析注意示例 ngi…

常见公式的几何解释

本文旨在深入探讨常见数学公式的几何意义,通过直观的图形和解释,帮助读者更好地理解并掌握这些公式的本质。文章首先概述了公式与几何图形之间的紧密联系,然后选取了几个典型的数学公式,进行详细解析。每个公式都将配以相应的几何…

Zynq 7000 系列之启动模式—JTAG启动

JTAG Boot(JTAG启动)是一种使用JTAG接口来启动设备的方法。JTAG(Joint Test Action Group)是一种国际标准测试协议,最初用于对芯片进行测试,现在已广泛应用于各种设备的调试和启动过程。在JTAG Boot过程中&…

是机遇?是未来?拥抱 AI Agent ,拥抱 AI 2.0时代~

✍️ 作者:哈哥撩编程(视频号同名) 博客专家全国博客之星第四名超级个体COC上海社区主理人特约讲师谷歌亚马逊演讲嘉宾科技博主极星会首批签约作者 🏆 推荐专栏: 🏅 程序员:职场关键角色通识宝…

社交媒体数据恢复:飞机 X

飞机 X数据恢复方法 在本文中,我们将探讨如何在不使用特定数据恢复软件的情况下尝试恢复飞机 X聊天记录和文件。请注意,这些方法并不保证100%的成功率,但它们可以在一定程度上帮助您恢复丢失的数据。 1. 检查最近的备份 如果您启用了飞机 …

【17-模型选择与调优:交叉验证和网格搜索在Scikit-learn中的实践】

文章目录 前言交叉验证:保证模型的稳健性理论基础Scikit-learn中的实现网格搜索:寻找最佳参数理论基础Scikit-learn中的实现应用示例结论前言 模型选择和调优是机器学习项目成功的关键步骤。在Scikit-learn中,交叉验证和网格搜索是两个强大的工具,用于选择最佳模型和调整参…

Qt Creator导入第三方so库和jar包——Qt For Android

前言 之前了解了在Android Studio下导入so库和jar包,现在实现如何在Qt上导入so库和jar包。 实现 下面是我安卓开发(需调用安卓接口的代码)的目录(图1),此目录结构和原生态环境(Android Studi…

如何反向查看某个命令所属的rpm包的2个方法?(rpm -qf `which xxx`和yum provides和 rpm -ql xxx.rpm)

文章目录 快速回忆方法1: rpm -qf方法2:yum provides 其他rpm如何查看某个rpm包里面包含哪些命令: rpm -ql主推方法1: rpm -ql方法2:yum info 其他查看rdma-core中包含哪些cmd:一些其他命令所在包探索 快速回忆 rpm -…

使用Gitbook生成电子书

背景 《Google工程实践文档》相对原文Google’s Engineering Practices documentation ,部分内容过时了。需要更新中文版,并使用Gitbook把Markdown文件转换成对应的PDF电子书。   上一次生成PDF电子书是5年前,当时生成电子书的环境早已不在…