[山东大学操作系统课程设计]实验2

news2024/12/23 9:10:10

0.写在前面

其实昨天就把这篇写完了,可是遇到了一些突发事件,暂时还没想好自己的出路在哪,争取这两天把课程设计的实验全都写完吧。。。。。我知道大家现在都很难过,生活上,学业上,事业上。。。。但是还是希望大家能一起加油度过这段日子

1.关于实验的说明

首先这个实验的最基本要求,就是修改一下nachos的线程调度策略,让其变为具有优先级的县城调度。换言之,就是加上优先级属性,然后在调度(对于这个实验来说,调度可以具体化一些,就是线程从就绪态转化为运行态,然后进入队列或者cpu的过程中)。

因为实验本身不太难(落实到代码上,只需要改动两三个地方就可以了,加起来不到10行代码),而且其实我也不会c,源码的解释在这篇可能不是很地道和详细,但我还是尽力去完成这些东西,还是那句话,如有不足,还望指出,感激不尽

2.关于一些模块以及函数的解析

线程相关函数的分析



//构造函数

Thread::Thread(const char* threadName,int threadPriority=0)

//系够函数
Thread::~Thread()

//创建新的线程
void 
Thread::Fork(VoidFunctionPtr func, _int arg)

//检查线程是否超出内存
void
Thread::CheckOverflow()

//结束线程(转化为结束态)
void
Thread::Finish ()

//转化为就绪态
void
Thread::Yield ()

//转化为阻塞态
void
Thread::Sleep ()

//为线程分配空间
void
Thread::StackAllocate (VoidFunctionPtr func, _int arg)
  
//不知道干啥的,应该没啥用
void
Thread::SaveUserState()


void
Thread::RestoreUserState()

至于schedule下面只需要知道这一个函数就可以了,这个函数使用来切换线程的

void
Scheduler::ReadyToRun (Thread *thread)
{
    DEBUG('t', "Putting thread %s on ready list.\n", thread->getName());

    thread->setStatus(READY);
    // readyList->Append((void *)thread);
    readyList->SortedInsert((void *)thread,thread->getPriority());
}

3.关于实验需要做什么

好的吧,那么我们直接开始解析内容了。

首先实现说明,我们需要修改的模块只有两个,schedule系列(用来管理调度),thread(用来管理线程实体本身)就可以将正常的非抢夺式线程调度,转化为一个优先级调度。最后在threadTest下面fork几个新的线程。

而具体的实现思路其实就两点,剩下的都是nachos本身完成了实现:

1. 线程本身,需要注明优先级

2. 而优先级调度的实现,在这里我们是通过在运行态转化为就绪态,也就是进入就绪队列的时候,实现这样一个”按优先级顺序插入“,而不是直接插入尾部。

好吧,我知道这样解释其实挺苍白的,所以我们在这里直接解释一下如何进行操作

首先是对于线程本身这个类:

3.0:准备工作

需要将如下几个文件从/threads中复制过来

3.1:对于thread.cc和thread.h的修改

对于头文件来说,我们需要做的是优先级,在这里用一个整数来进行表示

然后,增加一个获取优先级的方法,让整个系统封装严密一些

在然后,修改thread的构造方法声明,添加优先级参数:

这样,在h文件中得到的一个类,(改动的部分已经在下面了)

class Thread {

  public:

    Thread(const char* debugName , int priority=0);		// initialize a Thread 
   
    int getPriority(){ return priority;} //返回优先级的方法

  private:

    int priority;

 

然后是更改一下thread.cc文件中,关于构造方法的具体实现

(注意构造方法中,优先级属性请设置为默认参数,因为有些本实验涉及不到的东西会遇到一些问题,因此需要保留原本的构造方法的有效性)

3.2:对于scheduler.cc以及scheduler.h的修改

优先级的实现,在thread上已经完成了,这个不用多说

接下来是如何根据优先级实现调用,其实实现原理就是从”先进先出“的尾部插入,到”优先级插入“,而这个函数,nachos已经帮我们实现了

直接修改其中的readytorun函数即可

void
Scheduler::ReadyToRun (Thread *thread)
{
    DEBUG('t', "Putting thread %s on ready list.\n", thread->getName());

    thread->setStatus(READY);
    // readyList->Append((void *)thread); 将这个修改为别的
    readyList->SortedInsert((void *)thread,thread->getPriority());
}

 3.3:threadtest.cc文件

这个文件主要是用来进程的改动而已,在函数中新增几个两个线程即可

//----------------------------------------------------------------------
// ThreadTest
// 	Set up a ping-pong between two threads, by forking a thread 
//	to call SimpleThread, and then calling SimpleThread ourselves.
//----------------------------------------------------------------------

void
ThreadTest()
{
    DEBUG('t', "Entering SimpleTest");

    Thread *t1 = new Thread("forked thread1");
    Thread *t2 = new Thread("forked thread2");
    Thread *t3 = new Thread("forked thread3");

    t1->Fork(SimpleThread, 1);  //第二个参数是序号
    t2->Fork(SimpleThread, 2);
    t3->Fork(SimpleThread, 3);
    SimpleThread(0);
}

最后按照我们实验1的方式,使用make指令编译出可执行文件即可执行了。

4.实验内容(正文报告)

1. 分析说明原有的Nachos调度流程

原有的nachos调度流程,虽然已经实现了”优先级属性”在listElement中,但是本质上在插入的时候,对每个线程封装的优先级均为“0”,也就是先进显出的调度策略。

2. 设计并且实现具有静态优先级的非抢占式线程调度策略。

修改内容:

(1)首先引入需要的模块

需要将如下几个文件从/threads中复制过来

(2)然后对应模块进行修改

对于头文件来说,我们需要做的是优先级,在这里用一个整数来进行表示

然后,增加一个获取优先级的方法,让整个系统封装严密一些

在然后,修改thread的构造方法声明,添加优先级参数:

这样,在h文件中得到的一个类,(改动的部分已经在下面了)

class Thread {

  public:

    Thread(const char* debugName , int priority=0);		// initialize a Thread 
   
    int getPriority(){ return priority;} //返回优先级的方法

  private:

    int priority;

 

然后是更改一下thread.cc文件中,关于构造方法的具体实现

优先级的实现,在thread上已经完成了

接下来是如何根据优先级实现调用,其实实现原理就是从”先进先出“的尾部插入,到”优先级插入“,而这个函数,nachos已经实现了

直接修改其中的readytorun函数即可

void
Scheduler::ReadyToRun (Thread *thread)
{
    DEBUG('t', "Putting thread %s on ready list.\n", thread->getName());

    thread->setStatus(READY);
    // readyList->Append((void *)thread); 将这个修改为别的
    readyList->SortedInsert((void *)thread,thread->getPriority());
}

这个文件主要是用来进程的改动而已,在函数中新增几个两个线程即可

//----------------------------------------------------------------------
// ThreadTest
// 	Set up a ping-pong between two threads, by forking a thread 
//	to call SimpleThread, and then calling SimpleThread ourselves.
//----------------------------------------------------------------------

void
ThreadTest()
{
    DEBUG('t', "Entering SimpleTest");

    Thread *t1 = new Thread("forked thread1");
    Thread *t2 = new Thread("forked thread2");
    Thread *t3 = new Thread("forked thread3");

    t1->Fork(SimpleThread, 1);  //第二个参数是序号
    t2->Fork(SimpleThread, 2);
    t3->Fork(SimpleThread, 3);
    SimpleThread(0);
}

最后按照我们实验1的方式,使用make指令编译出可执行文件,并且运行这个可执行文件,得到结果如下

3. 上下文切换次数变化

首先节选一部分,指令nachos -t d指令打印出来的信息

经过对比发现,和simpleThread的条目数目对不上。

实际上这个结果的原因是由于上下文的频繁切换,因为simpleThread中的执行逻辑是简单的线程放弃cpu以及切换,也可能是频繁的上下文切换导致了错误。

通过如下的修改方式可以实现一定程度的缓解,通过缓冲区统一打印,减少一定程度上的上下文切换频率。

void
SimpleThread(_int which)       //
{
    int num;
int p=0
char buffer[100];
    
    for (num = 0; num < 5; num++) {   //减少上下文切换次数差不多就是在这里
        p+=snprintf(buffer+printCount,........)//累加到缓冲区中
    }
    printf('%s',buffer)
    currentThread->Yield()
}

4. 优先级调度老化的实现

线程调度老化指的是随着时间的推移,线程优先级降低或者失去掉去机会的情况。

对于nachos来说,增加老化机制的方法可以为在线程切换并且转化为就绪态,在插入就绪队列之前,可以适当对优先级进行自减操作。

首先需要对thread进行进一步的修改,增加setPriority来修改线程的优先级

然后在Yield方法中,在线程对象重新被放入readyList之前,将其优先级属性降低即可。

这样即可实现老化机制

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

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

相关文章

全系降3万,一把干到底,极越「智取」特斯拉

作者|德新 编辑|王博 11月30日&#xff0c;极越01官宣全系降价3万。 这意味着21.99万起步的极越01 Max&#xff0c;成为这个市场上入门门槛最低的带有城市智能驾驶辅助功能的车型。 要知道这是一台比Model Y大了一圈&#xff0c;全系配置了高阶智驾硬件&#xff0c;全系配高…

【工具分享】| 阅读论文神器 使用技巧 AI润色 AI翻译

文章目录 1 使用技巧1.1 功能一 即时翻译1.2 功能二 文献跳转1.3 功能三 多设备阅读1.4 功能四 小组讨论笔记共享1.5 功能五 个人文献管理 2 其他功能 超级喜欢Readpaper这一款论文阅读软件&#xff0c;吹爆他哈哈 为什么&#xff1f; 当然是他可以解决我们传统阅读论文的种种…

影响CSGO饰品价格涨跌的因素有哪些?

首先&#xff0c;饰品的交易是从市场进行的&#xff0c;市场终究是市场&#xff0c;是自由买卖的&#xff0c;必然存在供求关系以及资本操作&#xff0c;饰品价格的涨幅都是有道理或是有规律可循的。 1、价格上涨&#xff0c;最主要的影响因素来自于皮肤租赁市场的出现&#x…

简述MyBatis、MyBatis-Plus、以及MyBatis-Plus的简单运用

什么是MyBatis MyBatis是一个开源的Java持久层框架&#xff0c;用于简化与关系型数据库的交互。它通过将SQL语句与Java代码进行分离&#xff0c;提供了一种优雅的方式来处理数据库操作。 MyBatis的核心思想是将SQL语句与Java方法进行映射&#xff0c;使得开发人员可以通过配置…

【STM32】EXTI外部中断

1 中断系统 1.1 中断简介 中断&#xff1a;在主程序运行过程中&#xff0c;出现了特定的中断触发条件&#xff08;中断源&#xff09;&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理中断程序&#xff0c;处理完成后又返回原来被暂停的位置继续运行。 比如&a…

密码学实验三

第一题&#xff1a; 寻找满足特定条件的 e&#xff1b; 第一步&#xff1a; 第二步&#xff1a; 由式1.7知&#xff0c;给定e,p,q&#xff0c;就可计算出相应的RSA不动点的数目。因此设计算法步骤如下&#xff1a; 枚举找出所有与φ(n)互素的e。枚举所有满足条件的e&#xff…

c语言:模拟实现atoi函数

atoi函数的功能和用法&#xff1a; 主要功能&#xff1a;将字符串转换为整数。例如&#xff0c;将字符类型的“123”转换为整数123. #include <stdio.h> #include <stdlib.h>int main() {char str[] "123";int num atoi(str);printf("Converted …

刷题笔记12.01 贪心策略

P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 说最大不超过.不用高精度,好说 #include <bits/stdc.h> using namespace std; int n,n2,a; long long a1[10004],a2[10004],sum; int main() {ios::sync_…

C++-设计一个特殊类

目录 一.设计一个类&#xff0c;不能被拷贝 二.设计一个类只能在堆上创建对象 三.设计一个类只能在栈上创建对象 四. 请设计一个类&#xff0c;不能被继承 五.请设计一个类&#xff0c;只能创建一个对象(单例模式) 1.单例模式&#xff1a; 2. 饿汉模式 一.设计一个类&#x…

C#中GDI+绘图应用(柱形图、折线图和饼形图)

目录 一、柱形图 1.示例源码 2.生成效果 二、折线图 1.示例源码 2.生成效果 三、饼形图 1.示例源码 2.生成效果 GDI绘制的一些常用的图形&#xff0c;其中包括柱形图、折线图和饼形图。 一、柱形图 柱形图也称为条形图&#xff0c;是程序开发中比较常用的一种图表技术…

【AI】数据集Dataloader制作

以花朵分类的数据集来进行测试。 Oxford 102 Flowers Dataset 是一个花卉集合数据集&#xff0c;主要用于图像分类&#xff0c;它分为 102 个类别共计 102 种花&#xff0c;其中每个类别包含 40 到 258 张图像。 该数据集由牛津大学工程科学系于 2008 年发布&#xff0c;相关论…

[原创]Delphi的SizeOf(), Length(), 动态数组, 静态数组的关系.

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XXQQ: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、Delphi…

中学老师求职简历(精选9篇)

以下简历内容以中学老师招聘需求为背景&#xff0c;我们整理并修改了9篇全面、专业且具有参考价值的简历案例&#xff0c;大家可以灵活借鉴&#xff0c;希望能帮助大家在众多候选人中脱颖而出。 中学老师简历下载&#xff08;可在下制作下载&#xff09;&#xff1a;百度幻主简…

表的创建和管理

表的创建和管理 一条数据的存储过程标识符的命名规则MySQL中的数据类型管理和创建数据库创建数据库使用数据库修改数据库 创建表创建方式1创建方式2查看数据表结构 修改表追加一个列修改一个列重命名一个列删除一个列 重命名表删除表清空表 一条数据的存储过程 存储数据是处理数…

pycharm closing卡住 解决办法

别处看到的&#xff0c;亲测有效 1.升级 pycharm 到 2023.3 2.pycharm 主页 Help -> Find Action -> 输入 Registry -> 禁用ide.await.scope.completion PyCharm 2023.1.2版本关闭后一直显示正在关闭项目 - 知乎

CentOS系统环境搭建(二十一)——安装git并且配置ssh拉取github代码

centos系统环境搭建专栏&#x1f517;点击跳转 文章目录 安装git并且配置ssh拉取github代码1.git初始配置2.设置ssh3.设置GitHub4.拉取代码 安装git并且配置ssh拉取github代码 1.git初始配置 安装 yum install git验证 git --version配置用户名&#xff08;记得用你自己的…

C++中异常的栈展开概念

C中的异常栈展开是指&#xff0c;当某个函数中有异常产生&#xff08;这里不考虑是主动抛出的还是被动产生的&#xff09;&#xff0c;在异常被捕获之前的函数调用链上&#xff0c;函数不会正常执行返回&#xff0c;即异常产生之后的程序逻辑不会被执行。 &#xff08;注意&…

HarmonyOS开发准备(一) TypeScript基本语法

HarmonyOS开发准备(一) TypeScript基本语法 TypsScript官网&#xff1a;https://www.typescriptlang.org/play 可在官网 Playround 在线运行 Typescript 一、变量声明 // 创建 number(数值) 类型变量 let test_number: number 111 console.log(test_number&#xff1a;, tes…

教你把ChatGPT训练抖音爆款文案(附提示词)

刚好有圈子同学问到&#xff1a;如何把ChatGPT训练成1个抖音爆款写手&#xff0c;相信很多小伙伴日常也存在类似需求&#xff0c;用好一个GPT&#xff0c;让月薪5K的小助理快速变成3万月薪的运营。本期就给大家安排一期ChatGPT教程。接下来手把手演示ChatGPT调教和提示词方式一…

福州大学《嵌入式系统综合设计》实验十三:RTSP拉流与RTMP推流

一、实验目的 掌握基于算能平台的JPEG压缩编码方法以及开发环境&#xff0c;包括开发主机环境搭建&#xff0c;硬件嵌入式开发板的连接&#xff0c;云平台的配置&#xff0c;编码程序的编译、运行等。 二、实验内容 搭建实验开发环境&#xff0c;并编写静止图像jpeg格式编解…