Project_1

TCB任务控制块

processArgs()检测参数信息

new TCB.start(…)进入TCB类,调用构造函数初始化变量。、

创建一个新KThread:

如果当前线程为空,即第一个是主线程。将tcb块置为当前的TCB。实例化readyQueue为readyQueue分配参数。

如果当前线程不为空,则为当前线程实例化tcb。

KThread执行fork():

tcb.start():如果不是第一个线程,将TCB的running状态置为true,等待被start。则会执行waitForInterrupt()等待。

最高,将KThread加入readyQueue。

Task1:join()函数

在KThread被创建的时候,要添加一个waitQueue。即每一个KThread对应一个waitQueue,表明正在等待该线程执行完毕的所有线程。

一个线程的run()方法中,例如A调用B.join()

(A,B均为KThread对象),在调用 join()方法时,让当前的运行线程休眠。即A被挂起,加入到B的等待队列(waitQueue)中。B线程运行结束后,会调用Finish()方法从等待队列中取出一个KThread加入就绪队列,A才有可能继续运行。而且join()函数只会被调用一次,而且调用join()的不能是当前线程,所以给出如下断言。

finish()方法在runThread()中自动调用。但当前唯一运行的线程不能立刻被结束,需要在其他的线程begin()方法中保存运行状态,结束线程。

join()方法:

若当前线程状态非完成状态,则将线程挂到调用join()线程的等待队列(waitQueue<waitQueue是一个KThread的内部等待队列>)当中,并将currentThread.sleep(){

会将currentThread的状态置为 阻塞,并执行下一个线程}

finish()方法:

从当前线程的等待队列(waitQueue)中ready(){将线程加入就绪队列(readyQueue)}一个线程,并将自己sleep()。

Task2:Condition()条件变量

条件变量使线程可以睡眠等待某种条件出现,利用线程间共享全局变量进行同步的一种机制。其中有sleep(){使一个线程等待条件变量成立}、wake(){给出条件成立}。为了防止竞争,条件变量和一个互斥锁结合。锁也有自己的等待队列,一个线程要求获取锁(lock.acquire())的时候需要判断当前锁是否被占用,如果被占用则加入锁的等待队列。

声明互斥锁(conditionLock)和等待队列(waitqueue)

实现3个方法:sleep(),wake(),wakeAll()。条件变量是基于锁的,锁用来控制线程的互斥,条件变量用来控制公共资源的同步访问。

sleep():需要检查当前线程是否抓住锁。如果抓住锁,先关中断原子执行,再释放锁,然后将当前线程加入该条件变量的等待队列(sleep())。最后线程睡眠。即调用这个方法的线程将自己挂起到调用方法的条件变量的等待队列,阻塞自己的同时将自己拥有的锁交出去,被唤醒后等待锁的分配。

wake():唤醒条件变量等待队列中第一个线程。

Task3:Alarm()

timerInterrupt()在每一次timer产生时钟中断时遍历链表,检查链表中每个线程的信息,当满足等待时间(当前时间<list中的某个时间)时就把线程从队列中取出放入就绪队列。

waitUntil()使用一个链表可以存放线程以及线程信息。调用时,计算唤醒时间后,创建线程信息对象。将对象加入等待链表,等待时钟中断唤醒。

当前线程睡眠至少x时间周期,在定时器中断处理程序中将其唤醒。

注意:每次alarm()唤醒一个线程执行,该线程执行的时候会切换。执行时会导致timer又跳过500个滴答,所以即使两个线程的等待时间很近,但是执行时间会差500左右。

Task4:Communicator()

使一个通许对象实例中多个speaker和listener能够相互通讯。每一个Communicator类都有锁(保证操作的原子性)和两个条件变量用于保证speaker和listener的同步。

声明 speaker条件变量、listener条件变量、一个用于存储话的队列

speak():先获得锁,再检查是否有listener等待。如果有听者,将说的话放入语言队列,并唤醒一个listener。如果没有listener等待则将speaker等待的数量+1,将话放入语言队列后在speaker条件变量下sleep()。当speaker被唤醒时继续执行:应该去唤醒一个listener并将等待的speaker数量-1。

listener():先获得锁,如果speaker数量不为0则唤醒一个speaker;否则将listener数量+1后在listener条件变量下睡眠。

由于线程被fork()后是被加入readyQueue,按照readyQueue中的线程顺序执行。

有几种情况,程序执行的情况说明:

说者声明为s1,s2;听者声明为l1,l2;

说说听听

s1进入,listener=0;听者数量+1,保存内容,s1在speaker条件变量waitQueue中睡眠。

s2进入,listener=0;听者数量+1,保存内容,s1在speaker条件变量waitQueue中睡眠。

l1进入,speaker!=0,唤醒一个听者(s1加入就绪队列readyQueue),l1在listener条件变量waitQueue中睡眠。

l2进入,speaker!=0,唤醒一个听者(s2加入就绪队列readyQueue),l2在listener条件变量waitQueue中睡眠。

执行完上述过程后 readyQueue{s1,s2}

speaker.waitQueue{}

listener.waitQueue{l1,l2}

按照readyQueue中的顺序继续执行

s1被唤醒,继续执行。唤醒一个听者(l1加入就绪队列readyQueue),将说者数量-1,释放锁,返回。输出,s1执行结束。  s2被唤醒,继续执行。唤醒一个听者(l2加入就绪队列readyQueue),将说者数量-1,释放锁,返回。输出,s1执行结束。

l1被唤醒,继续执行。返回内容顶,输出,l1执行结束。

l2被唤醒,继续执行。返回内容顶,输出,l2执行结束。

说听说听:能够按照正常的执行流程进行执行

说听听说

听说说听

听说听说

听听说说

Task5:PriorityScheduler()

Note that:

you will need to change a line in nachos.conf that

specifies(指定)the scheduler class to use.

implement the methods:

must: getPriority(),getEffectivePriority(),setPriority()

optional: increasPriority(),decreasePriority()

primary idea:

在选择哪一个线程出等待队列时,应选择一个有最高有效优先级的线程。如果多个具有相同最高优先级的线程等待中,则选择一个在等待队列时间最长的线程

issue:priorityinversion

等待中的线程把它的优先级捐献给低优先级的线程。

priority donation implementationdetails:

一个线程的有效优先级是通过计算捐献者和接收者的 最大的优先级。

一个线程捐献优先级后不会丢失自己的优先级。

优先级捐献是传递的,A→B,B→C,则C具有A、B、C中的最高优先级。

LinkList<ThreadState>waitQueue = new LinkedList<ThreadState>();

waitQueue中保存的是线程的由优先级状态

ThreadState:KThread,priority,effectivePriority,waitQueue

ThreadState对象,用来把线程和优先级绑定在一起。内部有一个队列­(PriorityQueue对象)用来记录等待它的线程。

getEffectivePriority():计算有效优先级,遍历等待队列中所用线程的有效优先级,找出最大的优先级。首先在PriorityQueue类下创建一个装有KThread的linkedlist,即等待队列waitQueue,声明一个effectivePriority,遍历waitQueue,递归找出EffectivePriority最大的那个KThread,将它的Priority赋值给effectivePriorit。其中,waitQueue中的每个ThreadState对象都遍历自己的waitQueue,获取最高优先级。

waitForAccess()将需要等待获得资源的线程(调用方法的线程)加入一个等待队列等待调度。如果队列的主人不为空,且不是当前的线程,则将该线程还要加入主人的等待队列。

nextThread():返回下一个要执行的线程,遍历队列,计算出所有线程的有效优先级(计算的时候是递归计算每个ThreadState队列中每个线程的有效优先级,大于自己的优先级,则将它的有效优先级赋给自己),取出有效优先级最大的线程执行。

Task6:Boat()

theyhave only one boat which can carry maximally two children or one adult(but notone child and one adult).

Theboat can be rowed back to Oahu,but it requires a pilot to do so.

调用Boat.begin()是父线程,你的调度机制不能依赖事先知道有多少孩子和成人

不能有忙式等待

成人:

因为一个船只能载一个成人,成人在两个岛之间往返是无用的,所以成人只用考虑从Oahu岛到Molokai岛。

成人可以从Oahu岛岛Molokai岛的条件:
          船在Oahu岛、成人可以出行(Molokai岛至少有一个孩子,因为如果Molokai岛没有孩子则船无法从Molokai岛再返回Oahu岛)

如果成人不可以出行则将成人线程sleep();

否则成人划船去Molokai:

bg.AdultRowToMolokai();   //adult to Molokai

adult_inOahu--;       //在Oahu的成人数量-1

adult_inMolokai++;    //在Molokai的成人数量+1

adult_can_go =false;  //这一次是成人走,下一次必须是孩子走。因为要保证Molokai要至少有一个孩子

boat_Oahu = false;    //成人过去了,船也过去了。

成人到达Molokai岛后,wake()一个在Molokaisleep()的孩子,让他将船划回Oahu。

孩子:

由于成人不能划船,因此孩子必须在Oahu岛和Molokai岛之间往返划船,因此除非旅行结束否则每一个孩子都必须一直做事,因此要设置一个while循环。孩子可能在Oahu岛和Molokai岛

Oahu岛:

如果船没在Oahu岛、或者成人可以走了。孩子不能出行,则孩子在Oahu 睡眠。

if(!boat_Oahu||adult_can_go||newOne){

//如果船没在Oahu、或者该成人走了,该孩子睡眠

children_condition_Oahu.sleep();

}

否则孩子即将出行:

孩子在船上有两种情况:

作为pilot:

把此线程(孩子)的状态设为不在Oahu岛(在Molokai岛),在Oahu岛的孩子减一个,在Molokai岛的孩子增加一个。因为他是pilot则把isPilot设为false,唤醒另一个孩子一起走。到达Molokai岛后sleep。

作为passenger:

因为最后一次运送必然是两个孩子划船去M岛,所以孩子作为乘客时要判断运送是否即将完成。(在O岛的成人为0,减少一个作为船长的孩子后只剩一个孩子)。如果此次运送不是最后一次,则下次运送可以是成人(下次船在O岛时,M岛至少有一个小孩),如果成人数量不为0,将成人运输标志置为true。在此乘客与船长孩子过去后,就没有孩子船长了,isPilot置为true为下次运输设置变量。如果此时运输没有完成,唤醒一个M岛的孩子后,睡眠。

Molokai岛:

划船去O岛,设置孩子状态、船状态,通过状态判断下一次该谁走了就去唤醒谁:如果成人数量为0,则唤醒孩子;否则,根据是否满足成人可以走的条件,唤醒成人或孩子。

Nachos project1 领悟相关推荐

  1. “领悟”的价值是什么?思维能力训练问答

    "领悟"的价值是什么? 是让我们明白知识的价值在于运用.许多人认为知识会运用自己,这种想法大错特错. 每个人面前都敞开着一条路, 高贵的灵魂攀爬高处的路, 低贱的灵魂摸索低处的路, ...

  2. 领悟Web设计模式(转)

    领悟Web设计模式 本文发表在<程序春秋>2004年1期 摘要 本文介绍了在.NET框架下应用Web设计模式改进WebForm程序设计的一些基本方法及要点. 关键字 设计模式,ASP.NE ...

  3. 《高性能javascript》 领悟随笔之-------DOM编程篇(二)

    <高性能javascript> 领悟随笔之-------DOM编程篇二 序:在javaSctipt中,ECMASCRIPT规定了它的语法,BOM实现了页面与浏览器的交互,而DOM则承载着整 ...

  4. 操作系统课设--NACHOS试验环境准备、安装与MAKEFILE分析

    山东大学操作系统课设lab1 实验一 NACHOS试验环境准备.安装与MAKEFILE分析(lab1) 实验环境: 分析记录: 1. 准备虚拟机下LINUX宿主操作系统环境 2. NACHOS实验代码 ...

  5. Android -- 带你从源码角度领悟Dagger2入门到放弃(一)

    1,以前的博客也写了两篇关于Dagger2,但是感觉自己使用的时候还是云里雾里的,更不谈各位来看博客的同学了,所以今天打算和大家再一次的入坑试试,最后一次了,保证最后一次了. 2,接入项目 在项目的G ...

  6. 从海天信息化的三起三落领悟CIO的真谛

    海天集团信息化的成功来源于企业管理层的远见卓识和创新开放,当然这与海天集团各级员工的努力也分不开.在海天集团有这样一个人,他不仅见证了海天近十年信息化的发展历程,更为企业信息化的实施与发展立下了汗马功 ...

  7. 【机房收费系统】多么痛的领悟

    这次机房收费系统,是全部的项目中,自己完毕的最不惬意的了. 时间之长.效率之慢.一開始.就感觉无从下手,但总会相信自己能慢慢的进入状态.最终有机会自己练练手了.也自觉得之前自己设计模式学的还不错.也最 ...

  8. 《看聊天记录都学不会C语言?太菜了吧》(11)2分钟领悟数组

    好消息2020年4月13日晚7.30我在CSDN开播,等你来聊天 预约连接:https://live.csdn.net/room/A757291228/MJWK0Gem 本系列文章将会以通俗易懂的对话 ...

  9. 一篇文章带你领悟 Frida 的精髓(基于安卓8.1)

    转载(一篇文章带你领悟Frida的精髓(基于安卓8.1)):https://www.freebuf.com/articles/system/190565.html <Frida操作手册>: ...

最新文章

  1. mysql 按照范围选择_选择MySQL范围内的特定行?
  2. Linux 下文件打包和压缩
  3. 5.1 上网本安装安卓x86_生信工具 | antiSMASH 安装教程
  4. 微软发布Azure SignalR Service的预览版本
  5. mysql储存过程编程,MySQL 5.0存储过程编程入门
  6. Spark _09资源调度和任务调度
  7. Oracle 建立包 和 包体
  8. PostgreSQL 的 target_list分析(五)
  9. php 定时缓存,php定时清理缓存文件的简单示例
  10. oracle 的wecate函数,1.Oracle中decode()函数用法
  11. win10启动项_win10 -- 取消不需要的开机启动项和服务项加快win10系统开机速度
  12. lpc2000 filash utility 程序烧写工具_重点必看 | 取证小程序开发之第四届美亚杯硬盘信息快速解题...
  13. ModBus TCP/IP协议
  14. fisco bcos DagTransferUser.java 源码解析阅读注释
  15. Linux系统攻略关于vi替换命令的使用说明
  16. Wed Aug 03 19:48:03 +0800 2022这种字符串,怎么转成时间格式年月日
  17. JS实现抽奖活动程序
  18. java好看的图形界面_java写出图形界面
  19. linux光标变成圆圈,Ubuntu字体美化之安装使用准圆字体(附图)
  20. 设计模式学习笔记(C++实现)(七)--适配器模式

热门文章

  1. 计算机跨考专业基础差复试,跨考计算机过来人教你备考:从初试到复试
  2. Linux 只查找两层备份目录文件大小
  3. android app unlock sim pin,android Sim卡锁定 pin解锁流程学习
  4. LINUX IIO子系统分析之五IIO BUFFER子模块实现分析
  5. Paper翻译:《A Novel Convolutional Neural Network Based Model for Recognition and Classification of App》
  6. php+科研课题管理 毕业设计-附源码170914
  7. Android开发酒店预定预约管理系统
  8. 通用路由封装协议--GRE的简单配置
  9. 2012年河北金融学院csdn招新动员大会
  10. 根据原厂uboot进行移植