nachos

nachos实验记录

  • 实验一
    • 分析threads文件夹内容
      • thread
      • scheduler
      • 初始化函数Initialize()的工作
      • main()函数的工作
    • gdb基本使用
  • 实验三
    • 分析synch文件
    • 实验内容

实验一

分析threads文件夹内容

思路:通过thread类中的方法,来调用schedule类中的调度函数,实现线程的创建,就绪,运行,阻塞和结束五种状态的转换。

thread

  1. 创建线程:fork()。首先为线程分配栈资源(StackAllocate()),然后将线程状态设为就绪态(setStatus()),并放入就绪队列中(Append()),等待被调度即可。
  2. 线程阻塞:sleep()。首先将状态设置为阻塞态,然后从就绪队列中寻找新的线程来调度(FindNextToRun()),如果就绪队列中有线程就可以执行该线程(run()),如果就绪队列中没有线程则阻塞等待时钟中断到来(idle())。
  3. 线程切换:yield()。 从就绪队列中寻找新的线程来调度(FindNextToRun()),如果就绪队列中有线程就可以执行该线程(run()),同时将当前运行的线程放入就绪队列中(ReadyToRun());如果就绪队列中没有线程,则修改状态后直接退出即可。(区别于sleep(),yield()不会进入阻塞等待状态)
  4. 线程结束:finish()。先将线程标记为待删除的线程(Run()中进行删除),然后直接调用sleep()即可。为什么不调用yield():因为yield()虽然也释放cpu资源,但却将线程再次放入就绪队列中,而线程结束则意味着线程不需要再使用cpu,因此不应该再放入就绪队列中,调用sleep()则正好满足要求。

scheduler

  1. 寻找下一个运行的线程:FindNextToRun()。查看就绪队列中是否还有线程,如果有就从就绪队列中删除这个线程,并将其返回;如果没有线程则返回NULL。
    准备执行线程:ReadyToRun()。本质上就是创建到就绪态的转换,先将线程状态设为就绪态(setStatus()),然后将其放入就绪队列中即可(Append())。
  2. 执行线程:Run()。本质上就是就绪态到运行态的转换,先将线程状态设为运行态(setStatus()),然后进行上下文的切换(SWITCH()),最后判断被调度下去的线程是否需要销毁(finish()中进行的设置),如果要销毁那么就进行destory。

初始化函数Initialize()的工作

这个属于system类,即当执行一个main()函数时,操作系统自己进行的初始化工作。首先进行硬件资源如磁盘和网络设备的初始化工作,这里频繁使用ifdef,endif的搭配组合,工程项目中须要掌握这点。之后进行中断,调度队列,时钟的初始化。然后便可以创建main()主线程,并将其设为运行状态。

main()函数的工作

注意,这个main()函数并不是我们写的main()函数,而是nachos操作系统运行的内核程序,因为操作系统本质上也是一个程序,而nachos作为一个模拟的操作系统也自然需要去运行。main()函数首先调用Initialize()函数进行初始化工作,需要关注的是之后调用了ThreadTest()函数做测试,其中又调用了fork()创建了新的线程,并用新的线程和主线程均调用了SimpleThread()函数,但是传递的参数却不同,因此执行结果自然不同。

gdb基本使用

  1. 查看函数地址:首先list,然后找到要查看的函数位置,利用break设置断点即可。
  2. 查看线程对象地址:首先list,找到创建线程的代码位置,并利用break在创建线程返回值的位置设置断点,然后用run命令运行线程,到达这个位置时会暂停,此时利用p查看线程地址即可。
  3. 查看汇编代码的返回地址:可以用break在函数入口打断点,然后利用disass查看汇编代码,由于函数返回时一定会将返回地址放入寄存器中,则可以在返回的汇编代码的下一步中,利用info r查看寄存器内容,从而得到返回地址。需要注意的是,s和n命令都是c语言级的,想要单步执行汇编代码,需要利用si和ni,这些命令是汇编级的。

实验三

分析synch文件

首先需要了解的是,list文件中自己实现了链表节点,并基于此实现了链表类,然后在synch文件中利用这个链表实现了信号量,互斥锁和条件变量。其中信号量主要是维护了一个等待当前信号量的线程队列和信号量的值,而互斥锁则是维护了一个大小为1的信号量和锁的拥有者,由于本次实验我们使用信号量和互斥锁来实现生产者消费者模型,因此条件变量不在此详述,只需知道条件变量和互斥锁配合也完全可以实现生产者消费者模型,这其实可以作为线程池的实现方式。

  1. P()操作:为了实现线程安全,信号量的操作必须是原子性的,而保证原子性的方法就是关掉中断,即禁止了线程切换。然后判断当前信号量的值是否为0,若为0则需要加入队列,并进入阻塞状态;若不为0则可以将信号量值减一,重新打开中断即可。
  2. V()操作:依然需要先关闭中断,然后判断当前队列中是否有等待的线程,若有则将其从等待队列中删除,并准备执行(ReadyToRun())。最后将信号量值加一,并打开中断。
  3. Acquire()操作:首先依然是关闭中断,然后修改锁的持有者,并直接调用P()操作即可,最后记得重新打开中断。
  4. Release()操作:首先关闭中断,然后锁的持有者设为NULL,并直接调用V()操作即可,最后记得重新打开中断。

实验内容

缓冲区是在ring文件中实现的,就是一个简单的数组,并用in和out标记当前插入和取出的位置。还需要注意的是由于是环形缓冲区,因此需要取余。
需要填充的只有prodcons文件,首先明确的是由于缓冲区是临界区,因此需要互斥锁;并且缓冲区的大小有限,不可能无限取,也不可能无限填充,因此需要生产者和消费者进行同步的信号量。因此完成的工作主要是信号量和互斥锁的初始化,以及生产者的填入数据和消费者的取出数据工作。由于初始时默认缓冲区大小为空,因此对应的取出信号量为0,而填入信号量则为缓冲区大小。此时消费者会进入阻塞状态,等待生产者填入数据。
当生产者填入数据时首先遵循先同步后互斥的原则,先调用填入信号量的P()操作,然后调用加互斥锁。然后将数据填入缓冲区中,最后再解锁和调用取出信号量的V()操作即可。
消费者取出数据道理也类似,先调用取出信号量的P()操作,再加锁。将数据取出后,再解锁和调用填入信号量的V()操作即可。

热门文章

暂无图片
编程学习 ·

exe4j详细使用教程(附下载安装链接)

一、exe4j介绍 ​ exe4j是一个帮助你集成Java应用程序到Windows操作环境的java可执行文件生成工具,无论这些应用是用于服务器,还是图形用户界面(GUI)或命令行的应用程序。如果你想在任务管理器中及Windows XP分组的用户友好任务栏…
暂无图片
编程学习 ·

AUTOSAR从入门到精通100讲(126)-浅谈车载充电系统通信方案

01 引言 本文深入研究车载充电系统策略,设计出一套基于电动汽车电池管理系统与车载充电机的CAN通信协议,可供电动汽车设计人员参考借鉴。 02 电动汽车充电系统通讯网络 电动汽车整车控制系统中采用的是CAN总线通信方式,由一个整车内部高速CAN网络、内部低速CAN网络和一个充电…
暂无图片
编程学习 ·

CMake(九):生成器表达式

当运行CMake时,开发人员倾向于认为它是一个简单的步骤,需要读取项目的CMakeLists.txt文件,并生成相关的特定于生成器的项目文件集(例如Visual Studio解决方案和项目文件,Xcode项目,Unix Makefiles或Ninja输入文件)。然…
暂无图片
编程学习 ·

47.第十章 网络协议和管理配置 -- 网络配置(八)

4.3.3 route 命令 路由表管理命令 路由表主要构成: Destination: 目标网络ID,表示可以到达的目标网络ID,0.0.0.0/0 表示所有未知网络,又称为默认路由,优先级最低Genmask:目标网络对应的netmaskIface: 到达对应网络,应该从当前主机哪个网卡发送出来Gateway: 到达非直连的网络,…
暂无图片
编程学习 ·

元宇宙技术基础

请看图: 1、通过AR、VR等交互技术提升游戏的沉浸感 回顾游戏的发展历程,沉浸感的提升一直是技术突破的主要方向。从《愤怒的小鸟》到CSGO,游戏建模方式从2D到3D的提升使游戏中的物体呈现立体感。玩家在游戏中可以只有切换视角,进而提升沉浸…
暂无图片
编程学习 ·

flink的伪分布式搭建

一 flink的伪分布式搭建 1.1 执行架构图 1.Flink程序需要提交给 Job Client2.Job Client将作业提交给 Job Manager3.Job Manager负责协调资源分配和作业执行。 资源分配完成后,任务将提交给相应的 Task Manage。4.Task Manager启动一个线程以开始执行。Task Manage…
暂无图片
编程学习 ·

十进制正整数与二进制字符串的转换(C++)

Function one: //十进制数字转成二进制字符串 string Binary(int x) {string s "";while(x){if(x % 2 0) s 0 s;else s 1 s;x / 2;}return s; } Function two: //二进制字符串变为十进制数字 int Decimal(string s) {int num 0, …
暂无图片
编程学习 ·

[含lw+源码等]微信小程序校园辩论管理平台+后台管理系统[包运行成功]Java毕业设计计算机毕设

项目功能简介: 《微信小程序校园辩论管理平台后台管理系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序做的辩论管理前台和Java做的后台管理系统: 微信小程序——辩论管理前台涉及技术:WXML 和 WXS…
暂无图片
编程学习 ·

树莓派驱动DHT11温湿度传感器

1,直接使用python库 代码如下 import RPi.GPIO as GPIO import dht11 import time import datetimeGPIO.setwarnings(True) GPIO.setmode(GPIO.BCM)instance dht11.DHT11(pin14)try:while True:result instance.read()if result.is_valid():print(ok)print(&quo…
暂无图片
编程学习 ·

ELK简介

ELK简介 ELK是三个开源软件的缩写,Elasticsearch、Logstash、Kibana。它们都是开源软件。不过现在还新增了一个 Beats,它是一个轻量级的日志收集处理工具(Agent),Beats 占用资源少,适合于在各个服务器上搜集日志后传输给 Logstas…
暂无图片
编程学习 ·

Linux 基础

通常大数据框架都部署在 Linux 服务器上,所以需要具备一定的 Linux 知识。Linux 书籍当中比较著名的是 《鸟哥私房菜》系列,这个系列很全面也很经典。但如果你希望能够快速地入门,这里推荐《Linux 就该这么学》,其网站上有免费的电…
暂无图片
编程学习 ·

Windows2022 无线网卡装不上驱动

想来 Windows2022 和 windows10/11 的驱动应该差不多通用的,但是死活装不上呢? 搜一下,有人提到 “默认安装时‘无线LAN服务’是关闭的,如果需要开启,只需要在“添加角色和功能”中,选择开启“无线LAN服务…
暂无图片
编程学习 ·

【嵌入式面试宝典】版本控制工具Git常用命令总结

目录 创建仓库 查看信息 版本回退 版本检出 远程库 Git 创建仓库 git initgit add <file> 可反复多次使用&#xff0c;添加多个文件git commit -m <message> 查看信息 git status 仓库当前的状态git diff 差异对比git log 历史记录&#xff0c;提交日志--pret…
暂无图片
编程学习 ·

用Postman生成测试报告

newman newman是一款基于nodejs开发的可以运行postman脚本的工具&#xff0c;使用Newman&#xff0c;可以直接从命令运行和测试postman集合。 安装nodejs 下载地址&#xff1a;https://nodejs.org/en/download/ 选择自己系统相对应的版本内容进行下载&#xff0c;然后傻瓜式安…
暂无图片
编程学习 ·

Java面向对象之多态、向上转型和向下转型

文章目录前言一、多态二、引用类型之间的转换Ⅰ.向上转型Ⅱ.向下转型总结前言 今天继续Java面向对象的学习&#xff0c;学习面向对象的第三大特征&#xff1a;多态&#xff0c;了解多态的意义&#xff0c;以及两种引用类型之间的转换&#xff1a;向上转型、向下转型。  希望能…