【操作系统】实验六 分析源代码

news2024/11/17 1:43:48

🕺作者: 主页

我的专栏
C语言从0到1
探秘C++
数据结构从0到1
探秘Linux

😘欢迎关注:👍点赞🙌收藏✍️留言

🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的很重要,有问题可在评论区提出,感谢支持!!!

文章目录

  • 前言
  • 实验六
    • 实验内容:
    • 实验过程:
      • 1. 下载内核源码
      • 2. 进程调度队列是如何组织的?
      • 3. 三种调度类型(SCHED_FIFO, SCHED_RR, SCHED_OTHER)的实现过程?
      • 4. 优先级是如何定义和动态变化的?
      • 5. 时间片的赋值?它与优先级的关系?
      • 6. 对实时进程和多CPU的支持?
      • 7. 评价Linux的调度策略,提出改进意见。
    • 实验小结

前言

本实验结论没有标准答案,请自行判断。

实验六

实验内容:

  1. 实验名称:分析源代码
  2. 实验任务:
    通过阅读源代码,分析研究linux的进程调度策略和算法。要求以源码为依据,回答下面的问题:
  • 进程调度队列是如何组织的
  • 三种调度类型(SCHED_FIFO, SCHED_RR, SCHED_OHTER)的实现过程
  • 优先级是如何定义和动态变化的
  • 时间片的赋值?它与优先级的关系?
  • 对实时进程和多CPU的支持
  • 评价linux的调度策略,提出改进意见。
  1. 源码版本
    Linux 5.15.1

实验过程:

1. 下载内核源码

使用这个网站下载:https://mirrors.edge.kernel.org/pub/linux/kernel

2. 进程调度队列是如何组织的?

在新版本的Linux内核中,比如说我的版本5.15.1,进程调度队列是由红黑树(rbtree)实现的。每个CPU都有一个运行队列(runqueue),其中包含了所有处于可运行状态的进程。每个进程都通过一个task_struct结构来表示,其中的调度信息存储在sched_entity和sched_rt_entity结构中。
在Linux内核的源码中,调度队列的结构定义在include/linux/sched.h文件中。这个文件包含了与进程调度相关的各种数据结构和函数声明。如图1 源码中task_struct的结构。

图1 源码中task_struct结构
以下是一个简化的sched.h文件片段,展示了与调度队列相关的数据结构:

struct task_struct {    /* ... */
    struct sched_entity se;
    struct sched_rt_entity rt;
    /* ... */
};
struct sched_entity {
    /* ... */
    struct rb_node run_node;
    /* ... */
};
struct rb_root runqueues[NR_CPUS];

在这个片段中,task_struct结构表示一个进程,其中包含了两个与调度相关的结构:se和rt。se表示一个普通的调度实体,用于实现基于优先级的调度,而rt表示一个实时调度实体,用于实现基于时间的调度。
每个CPU都有一个runqueues数组,这是一个红黑树(rbtree),用于存储所有处于可运行状态的进程。每个进程通过其se或rt结构中的run_node域链接到红黑树中。
下面是源码中rb_node的实现:

图2 源码中rb_node的结构
在运行队列中,进程按照优先级(对于se)或时间(对于rt)进行排序。调度器在调度时,会遍历红黑树,选择最高优先级(或最早到期时间)的进程进行执行。

3. 三种调度类型(SCHED_FIFO, SCHED_RR, SCHED_OTHER)的实现过程?

SCHED_FIFO和SCHED_RR是实时调度策略,它们都基于优先级调度,只是SCHED_FIFO是无时间片的,而SCHED_RR是有时间片的。SCHED_OTHER是普通的分时调度策略。调度类型在源码中的表示和优先级在源码中的表示如图3、4所示。

图3 调度类型在源码中的表示

图4 优先级在源码中的表示

SCHED_FIFO的实现过程:当一个进程被设置为SCHED_FIFO时,它的sched_priority字段会被设置为一个正值,表示其优先级。当调度器选择进程时,它会从最高优先级的进程开始,直到找到一个可运行的进程。如果最高优先级的进程不可运行,那么它会继续查找次高优先级的进程,以此类推。
SCHED_RR的实现过程:当一个进程被设置为SCHED_RR时,它的sched_priority字段也会被设置为一个正值,表示其优先级。此外,它还有一个时间片(time slice),用于限制它运行的时间。当调度器选择进程时,它会从最高优先级的进程开始,直到找到一个可运行的进程。如果最高优先级的进程不可运行,那么它会继续查找次高优先级的进程,以此类推。当一个进程用完了它的时间片后,它会被放入队列的尾部,等待下一次调度。
SCHED_OTHER的实现过程:当一个进程被设置为SCHED_OTHER时,它的sched_priority字段会被设置为一个负值,表示其优先级。当调度器选择进程时,它会从最低优先级的进程开始,直到找到一个可运行的进程。如果最低优先级的进程不可运行,那么它会继续查找次低优先级的进程,以此类推。
调度器从最低优先级的进程开始选择,主要是为了实现公平调度。这种做法可以确保每个进程都有机会得到执行,避免高优先级的进程长时间独占CPU资源,导致低优先级的进程饥饿。
在许多操作系统中,调度策略都会考虑到进程的优先级,以确保系统资源的合理分配。通过设置进程的优先级,可以控制进程的执行顺序,从而使得系统资源得到更加有效的利用。
操作系统通过判断在不同的策略下进行不同的行为,如图5所示:

图 5 某个函数根据调度策略不同进行选择

4. 优先级是如何定义和动态变化的?

我们可以在sched.c文件中搜索nice,可以看到如图6的描述:

图 6 源码中对nice值的描述
在Linux内核中,进程优先级是通过sched_priority字段定义的,该字段是一个32位的整数,范围从-20(最高优先级)到+19(最低优先级)。
进程的优先级可以通过系统调用nice()和setpriority()来动态调整。nice()系统调用可以调整进程的nice值(nice值与优先级之间的关系是nice值越低,优先级越高)。setpriority()系统调用可以直接调整进程的优先级。
通过命令man nice 命令查看,如图7所示。

图 7 查看手册中对nice值的描述
通过命令man setpriority查看,如图 8 所示。

图 8 查看手册中对setpriority值的描述

5. 时间片的赋值?它与优先级的关系?

在 Linux 内核中,时间片的赋值主要跟以下几个因素有关:
1.调度策略:针对不同的调度策略,比如 SCHED_OTHER、SCHED_BATCH、SCHED_IDLE、SCHED_FIFO、SCHED_RR,时间片的赋值是不同的。CFS(完全公平调度算法)用于 SCHED_OTHER、SCHED_BATCH、SCHED_IDLE 调度策略,而 SCHED_FIFO、SCHED_RR 则是实时调度策略。
2.进程优先级:对于 SCHED_FIFO 和 SCHED_RR 的实时任务,优先级(在 Linux 中表现为 rt_priority)是静态设定的,不过所有实时进程的优先级都高于普通进程。优先级越高的进程越先被调度,直到它完成任务或者出现更高优先级的线程抢占。
对于 CFS 调度的普通进程,优先级(在 Linux 中通过 nice 值来派生)影响的是每个进程的权重,即与每个进程关联的运行时长。nice 值越小,优先级越高,分配的 CPU 时间越多。
在新版 Linux 内核中,进程的时间片并不是固定的,不像早期的 O(1) 调度器有明确定义的时间片概念。CFS 调度器更注重进程之间的公平性,它使用虚拟运行时间(虚拟时钟)来度量进程的运行时间并按此公平调度。
以下是在 Linux 内核代码中找到的一些相关的源码部分:
普通任务的运行时间:CFS 调度器的运行时间(可以理解为时间片)在 kernel/sched/fair.c 这个文件中进行计算和更新,比如函数 entity_tick 中就更新了进程的虚拟运行时间,如图9所示。

图 9 函数 entity_tick的内容
此外,需要注意的是,调度策略、优先级、时间片等可以通过sched_setparam、sched_setattr 等系统调用进行设置。但这些调用主要用于设置调度策略和优先级,而非直接设置时间片长度。
在kernel/sched/sched.h文件中,可以找到关于优先级的定义:

#define MAX_PRIO        140#define DEFAULT_PRIO        120
struct sched_param {
    int sched_priority;
};
其中,MAX_PRIO是优先级的最大值,DEFAULT_PRIO是默认的优先级。
在kernel/sched/core.c文件中,可以找到关于nice值来调整优先级的代码:
static voidset_user_nice(struct task_struct *p, long nice)
{
    int old_prio, delta;
    if (nice < -20 || nice > 19)
        return;
    old_prio = p->static_prio;
    delta = 20 - nice;
    if (delta < 0) {
        delta = -delta;
        p->static_prio = old_prio - delta;
    } else {
        p->static_prio = old_prio + delta;
    }
}

这段代码展示了如何根据nice值(表示优先级)来调整静态优先级(static_prio)。

6. 对实时进程和多CPU的支持?

Linux内核支持实时进程和多CPU。实时进程可以通过sched_setscheduler()系统调用来设置调度策略(SCHED_FIFO或SCHED_RR)。多CPU支持通过每个CPU都有自己的运行队列来实现,每个运行队列都包含了所有在该CPU上可运行的进程。
以下是Linux内核代码中的一些部分,这些部分展示了对实时进程和多CPU的支持:
实时进程调度:在kernel/sched/sched.h文件中,定义了实时进程的宏,如图10所示。

图 10 调动策略的宏定义
在kernel/sched/sched.c文件中,实现了实时进程的调度函数:

static void sched_rt_period_timer(struct rq *rq){
    struct task_struct *curr = rq->curr;
    struct task_struct *next;
    if (curr->policy != SCHED_FIFO && curr->policy != SCHED_RR)
        return;
    /*
     * Reevaluate all tasks with equal priorities:
     */
    for_each_task_in_rq(rq, next) {
        if (next->prio == curr->prio)
            resched_task(rq, next);
    }
}

多CPU支持:在kernel/sched/core.c文件中,实现了多CPU调度的代码:

void __sched __schedule(void){
    ...
    cpu = smp_processor_id();
    rq = cpu_rq(cpu);
    ...
}

这个函数在选择下一个要运行的进程时,会首先获取当前CPU的ID,然后获取与该CPU对应的运行队列。

7. 评价Linux的调度策略,提出改进意见。

Linux的调度策略已经比较成熟,但是仍然有改进的空间。例如,可以通过引入更精细的优先级机制,如按进程组、用户或进程类型来设置优先级,以提高调度的公平性和效率。此外,还可以考虑引入更先进的调度算法,如基于反馈的控制理论或机器学习的方法,以实现更智能的调度决策。

实验小结

在本次实验中,我们通过分析 Linux 内核源码,探索了 Linux 的进程调度策略和算法。尽管我们已经对源码做了深入的研究,但是遇到了一些问题,也产生了一些值得注意的事项,以及识别了一些待提高的能力。

存在问题:

  1. 源代码理解难度大:Linux 内核源代码是底层的操作系统代码,其复杂性和深度使得对其的理解和分析较为困难。其中涉及的概念,如调度算法、优先级和时间片等,需要具备扎实的操作系统理论知识和强大的代码阅读能力。
  2. 实验结果的实用性:尽管我们对源代码有了一定的理解,但如何将这些理解转化为改进 Linux 内核的实际操作尚不清楚。

注意事项:

  1. 源码版本:Linux 内核源码更新频繁,新的版本可能会包含新的调度算法或策略,因此我们需要时刻关注内核源码的更新,理解新版本的特性和变化。
  2. 细节分析:在阅读源码时,需要注意细节,理解代码的功能,以便更准确地理解 Linux 的调度策略。

有待提高的能力:

  1. 深入理解底层代码:更好地理解 Linux 内核源代码,理解其背后的设计思想和实现细节,是需要长期磨练的技能。我们需要进一步提高我们阅读和理解底层代码的能力。
  2. 实践转化:如何把对源码的理解转化为实际的改进或应用,这是一个值得我们深思的问题,也是我们需要努力提升的能力。

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

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

相关文章

Python爬虫 l 中国农药信息网的农药登记数据

一、爬取目标 二、完整源码 #""""""""""""""""""""""""""""""""""""""…

Docker网络及资源控制

目录 1.Docker网络 Docker网络实现原理 Docker的网络模式 host模式 container模式 none模式 bridge模式 自定义网络 2.资源控制 CPU资源控制 设置CPU使用率上限 设置CPU资源占用比 设置容器绑定指定的CPU 对内存使用的限制 对磁盘IO配额控制&#xff08;blkio&a…

泰迪科技最新大数据法律监督模型解决方案

大数据法律监督平台是基于监督数据整合管理平台、监督模型构建平台、内置模型库以及法律监督线索管理平台打造的一套服务于检察机关法律监督工作的专业化系统。通过数据采集、融合、挖掘、建模、展现等一系列能力&#xff0c;辅助检察官从纷繁复杂的数据中&#xff0c;开展多维…

手拉手JavaFX UI控件与springboot3+FX桌面开发

目录 javaFx文本 javaFX颜色 字体 Label标签 Button按钮 //按钮单击事件 鼠标、键盘事件 //(鼠标)双击事件 //键盘事件 单选按钮RadioButton 快捷键、键盘事件 CheckBox复选框 ChoiceBox选择框 Text文本 TextField(输入框)、TextArea文本域 //过滤 (传入一个参数&a…

【嵌入式学习】C++QT-Day1-C++基础

思维导图&&笔记 见我的博客&#xff1a;https://lingjun.life/wiki/EmbeddedNote/19Cpp 作业&#xff1a; 提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数 要求使用C风格字符串完成 #include <iostream&…

【K8S】Service使用NodePort对外暴露应用

一、背景介绍 Pod是有生命周期的&#xff0c;当一个工作节点(node)销毁时&#xff0c;节点上运行的pods也会被销毁。ReplicationController会动态地在其他节点上创建Pod来保持应用程序的运行&#xff0c;每一个Pod都有一个独立的IP地址&#xff0c;甚至是同一个节点上的Pod。可…

软件安装SQLyog

SQLyog 安装配置使用 首先下载SQLyog 软件&#xff0c;并解压 选择自己操作系统的版本 双击点击 .exe 文件&#xff0c;进行安装 选择安装语言&#xff0c;默认中文&#xff0c;直接点击【OK】即可 点击【下一步】 先【勾选】同意协议&#xff0c;再点击【下一步】 …

男主角展现炸裂演技,演绎方式独具匠心,令人叹为观止

♥ 为方便您进行讨论和分享&#xff0c;同时也为能带给您不一样的参与感。请您在阅读本文之前&#xff0c;点击一下“关注”&#xff0c;非常感谢您的支持&#xff01; 文 |猴哥聊娱乐 编 辑|徐 婷 校 对|侯欢庭 在漫长的等待之后&#xff0c;《要久久爱》这部都市情感剧终…

图中点的层次——树与图的广度优先遍历

问题描述 代码实现 #include <cstring> #include <iostream> #include <algorithm>using namespace std;const int N 1e5 10;int n, m; int h[N], ne[N * 2], e[N * 2], idx; int d[N]; // 从节点1到当前节点的距离 int q[N * 2]; // 数组模拟队列void ad…

西安石油大学C++上机实验汇总

考试题难度就像第三章第五章课后题的难度 基础知识一定要掌握&#xff01;&#xff01;&#xff01; 上机一&#xff1a;类与对象程序设计&#xff08;2 学时&#xff09; 上机目的 掌握声明类的方法。掌握类和类的成员的概念以及定义对象的方法。掌握构造函数和析构函数的…

Salesforce Lightning 的 Close Case 按钮无法批量关闭 Case 的原因和解决方法

为 Lightning 页面添加了自定义的 Close Case 按钮&#xff08;方法可参考&#xff1a;https://www.simplysfdc.com/2021/01/salesforce-mass-close-case.html&#xff09;后&#xff0c;可能会出现无法批量关闭 Case 的情况。 选中多个 Case&#xff0c;再点击 Close Case 按…

微信小程序开发position等于static、relative、absolute、fixed、stricky时元素显示详细介绍

No Position 不设置position时显示,以红色元素做测试: Static 元素根据界面正常流进行定位。top、right、bottom、left 和 z-index 属性不起作用。这是默认值。 红色元素设置position: static,显示如下: Relative 元素根据界面正常流进行定位。以元素当前位置为基准,根…

C语言和C++中不定参数解析

你所看到的惊艳&#xff0c;都曾被平庸历练 文章目录 简介C语言不定参数不定参宏函数 C不定参数方法一&#xff1a;递归展开方式二&#xff1a;折叠表达式方法三&#xff1a;逗号表达式 总结 简介 相信学过c/c的佬们都知道&#xff0c;如果一个函数将自己的参数确定好后&#…

泛微智能公文,为党政机关配备一位7*24小时公文助手,办文更高效

政务数字化智能水平明显提升是数字中国建设目标之一&#xff0c;平台化、智能化已成为政务协同办公的未来发展趋势&#xff0c;政府机关持续加强新技术全流程应用。 公文办理作为党政机关单位日常工作任务中重要的一环&#xff0c;泛微在全程数字化的公文管理体系中融入智能化技…

【GAMES101】Lecture 09 纹理贴图 点查询与范围查询 Mipmap

目录 纹理贴图 纹理放大-双线性插值 点采样纹理所带来的问题 Mipmap 各向异性过滤 纹理贴图 我们在之前的着色里面说过如何给物体上纹理&#xff0c;就是对于已经光栅化的屏幕点&#xff0c;就是每个像素的中心&#xff0c;去寻找对应纹理的映射位置的纹理颜色&#xff0…

SWMM模型INP解析

.INP文件解析 [OPTIONS]&#xff1a;SWMM软件运行前需要设置的参数 [RAINGAGES]雨水节点&#xff0c;核心设置雨水时间序列&#xff0c;可为INP内部数据也可为外部txt数据&#xff0c;TIMESERIES对应【TIMESERIES】模块&#xff0c;TS_1为时间序列名称 [TIMESERIES]&#xff0…

ELK之Grafana添加钉钉告警信息

Grafana版本如下&#xff1a; [roottest data]# grafana-server -v Version 8.4.6 (commit: c53173ff6, branch: HEAD)一、新建钉钉群&#xff0c;并自定义一个机器人 点击右上角设置 ------》 智能群助手 ------》 添加机器人 ------》右侧设置按钮 ------》点击自定义&…

记一次SPI机制导致的BUG定位【不支持:http://javax.xml.XMLConstants/property/accessExternalDTD】

1、前因 今天在生产环境启用了某个功能&#xff0c;结果发现有个文件上传华为云OBS失败了&#xff0c;报错如下&#xff1a; Caused by: java.lang.IllegalArgumentException: 不支持&#xff1a;http://javax.xml.XMLConstants/property/accessExternalDTDat org.apache.xal…

ctfshow信息收集(web1-web20)

目录 web1 web2 web3 web4 web5 web6 web7 web9 web10 web11 web14 web15 web16 web17 web18 web19 web20 web1 根据提示的孩子开发的时候注释没有被及时删除 web2 js原因无法查看源代码 第一种方法 在url前加入 view-source&#xff1a; 会显示页面源代…

获取双异步返回值时,如何保证主线程不阻塞?

目录 一、前情提要二、JDK8的CompletableFuture1、ForkJoinPool2、从ForkJoinPool和ThreadPoolExecutor探索CompletableFuture和Future的区别 三、通过CompletableFuture优化 “通过Future获取异步返回值”1、通过Future获取异步返回值关键代码&#xff08;1&#xff09;将异步…