操作系统实验报告
班级物联网1302班
学号
姓名
实验2 进程状态转换及其PCB的变化
1.目的:
自行编制模拟程序,通过形象化的状态显示,深入理解进程的概念、进程之间的状态转换及其所带来的PCB内容、组织的变化,理解进程与其PCB间的一一对应关系。
2. 内容及要求:
1)设计并实现一个模拟进程状态转换及其相应PCB内容、组织结构变化
的程序。
2)独立编写、调试程序。进程的数目、进程的状态模型(三状态、五状
态、七状态或其它)以及PCB的组织形式可自行选择。
3)合理设计与进程PCB相对应的数据结构。PCB的内容要涵盖进程的基
本信息、控制信息、资源需求及现场信息。
4)设计出可视性较好的界面,应能反映出进程状态的变化引起的对应PCB
内容、组织结构的变化。
5)代码书写要规范,要适当地加入注释。
6)认真进行预习,完成预习报告。
7)实验完成后,要认真总结,完成实验报告。
3.使用的数据结构及说明:
在本实验中,主要用到的数据结构是PCB的结构,其中PCB的数据结构如下:enum Status
{
Running,
Ready,
Blocked,
Exit
};
struct PCB
{
int id; //进程号
int priority; //优先级
enum Status status; //进程状态
char name; //进程名称
};
struct Running
{
struct PCB pcb;
struct Running *pcbnext;
struct Running *header_running;
struct Ready
{
struct PCB pcb;
struct Ready *pcbnext;
};
struct Ready *header_ready, *tail_ready; struct Blocked
{
struct PCB pcb;
struct Blocked *pcbnext;
};
struct Blocked *header_blocked, *tail_blocked; struct Exit
{
int id;
char name;
struct Exit *pcbnext;
};
struct Exit *header_exit,*tail_exit;
4.流程图
开始
初始化进程控制块
初始化运行队列,就绪队列,阻塞队列,终止队列
进行进程调度
创建新进程?
就绪—运行
运行-就绪
运行—阻塞
阻塞—就绪
运行—终止
将新创建的进程放入就绪队列队尾
有正在运行的进程?
n
n
n
n
n
n
y
当前运行的进程优先级比被调度的进程优先级高?
y
原先运行的进程加入到就绪队列队尾,被调度进程开
始运行
n
y
有就绪进程?
原进程放入到就绪队列队尾。运行就绪队列第一个进程
y
y
n
原进程放入到阻塞队列队尾
y
有就绪队列?
运行就绪队列第一
个进程
n
y
有正在运行的进程?
有就绪进程?
·
将进程放入终止队
列队尾
有就绪进程?
运行就绪队列第一
个进程
n
y
n
y
y
n
y
将该进程放入就绪队列队尾
运行该进程
n
有就绪队列
n
运行该进程
y
5.程序源代码,注释及说明文字:
Main.c
#include
#include
#include"process.h"
#include
int main()
{
int i = 1;
int choice = -1;
header_running = (struct Running *) malloc(sizeof(struct Running)); //创建运行状态队列头
if (NULL == header_running)
{
perror("error");
exit(1);
}
header_running->pcbnext = NULL;
header_ready = (struct Ready *) malloc(sizeof(struct Ready));
//创建就绪队状态列头
if (NULL == header_ready)
{
perror("error");
exit(1);
}
header_ready->pcbnext = NULL;
header_blocked = (struct Blocked *) malloc(sizeof(struct Blocked));
//创建阻塞队状态列头
if (NULL == header_blocked)
{
perror("error");
exit(1);
}
header_blocked->pcbnext = NULL;
header_exit = (struct Exit *) malloc(sizeof(struct Exit));
//创建僵死状态队列头
if (NULL == header_exit)
{
perror("error");
exit(1);
}
header_exit->pcbnext = NULL;
tail_ready = header_ready;
tail_blocked = header_blocked;
tail_exit = header_exit;
printf("请输入要创建的进程个数\n");
scanf("%d", &num);
while (num <= 0)
{
printf("进程个数应大于0,请重新输入\n");
scanf("\n%d", &num);
}
for (i;i <= num;i++)
{
struct Ready *ready = (struct Ready *) malloc(sizeof(struct Ready));
if (NULL == ready)
{
perror("error");
exit(1);
}
printf("请输入进程 %d 的名称:\t",i);
scanf("\n%c", &ready->https://www.wendangku.net/doc/2a12349231.html,);
ready->pcb.id = i;
ready->pcb.priority = i;
ready->pcb.status = Ready;
ready->pcbnext = NULL;
tail_ready->pcbnext = ready;
tail_ready = ready;
}
printf("********************************************************* ******\n");
printf("******** 0---创建进程1---就绪-运行*************\n");
printf("******** 2---运行-就绪3---运行到阻塞*************\n");
printf("******** 4---阻塞-就绪5---运行-终止*************\n");
printf("********************************************************* ******\n");
while (1)
{
printf("\n请输入你要进行的转换:\t");
scanf("%d", &choice);
switch (choice)
{
case 0:status0();print();break;
case 1:status1();print();break;
case 2:status2();print();break;
case 3:status3();print();break;
case 4:status4();print();break;
case 5:status5();print();break;
default:printf("没有这个选项,请重新输入!!!\n");break;
}
printf("\n");
}
return 0;
}
//Process.c
#include
#include
#include"process.h"
/****创建进程***/
void status0(void)
{
struct Ready *ready = (struct Ready *) malloc(sizeof(struct Ready));
if (NULL == ready)
{
perror("error");
exit(1);
}
printf("请输入要创建的进程的名称:\t", &ready->https://www.wendangku.net/doc/2a12349231.html,);
scanf("\n%c", &ready->https://www.wendangku.net/doc/2a12349231.html,);
ready->pcb.id = num+1;
ready->pcb.priority = ++num;
ready->pcb.status = Ready;
ready->pcbnext = NULL;
tail_ready->pcbnext = ready;
tail_ready = ready;
}
/******就绪-运行********/
void status1(void)
{
if (NULL == header_running->pcbnext) //没有程序正在运行
{
if (NULL != header_ready->pcbnext) //就绪组中有就绪的进程
{
header_running->pcbnext = header_ready->pcbnext;
header_ready->pcbnext = header_ready->pcbnext->pcbnext;
header_running->pcbnext->pcb.status = Running; //进程状态变为运行状态
}
else printf("暂时没有就绪程序,请稍等!!!\n");
}
else //有正在运行的程序
{
if (header_running->pcb.priority < header_ready->pcb.priority) //正在运行的程序的优先级小于要调度的进程的优先级,进行调度
{
tail_ready->pcbnext = header_running->pcbnext;
header_running->pcbnext = header_ready->pcbnext;
header_ready->pcbnext = header_ready->pcbnext->pcbnext;
header_running->pcbnext->pcb.status = Running;
}
else printf("正在运行的进程的优先级大于被调度的进程的优先级,调
度失败\n");
}
}
/*****运行-就绪***/
void status2(void)
{
if (NULL != header_ready->pcbnext) //就绪队列不为空
{
tail_ready->pcbnext = header_running->pcbnext; //运行的
程序放在就绪队列尾部
tail_ready = tail_ready->pcbnext;
tail_ready->pcb.status = Ready; //状态变为就绪
tail_ready->pcbnext = NULL;
header_running->pcbnext = header_ready->pcbnext; //就绪队
列的第一个进程放到运行队列
header_running->pcbnext->pcb.status = Running;
header_ready->pcbnext = header_ready->pcbnext->pcbnext;
}
}
/****运行-阻塞***/
void status3(void)
{
tail_blocked->pcbnext = header_running->pcbnext; //将运行的
进程放到阻塞状态的队列尾部
tail_blocked = tail_blocked->pcbnext;
tail_blocked->pcb.status = Blocked;
tail_blocked->pcbnext = NULL;
header_running->pcbnext = NULL;
if (NULL != header_ready->pcbnext) //就绪组中有就绪的进程
{
header_running->pcbnext = header_ready->pcbnext; //就绪队列的第一个进程放到运行队列
header_ready->pcbnext = header_ready->pcbnext->pcbnext;
header_running->pcbnext->pcb.status = Running; //进程状态变为运行状态
}
}
/****阻塞-就绪***/
void status4(void)
{
char name;
struct Blocked *blocked = header_blocked;
printf("请输入要解除阻塞状态的进程的名称\t");
scanf("\n%c", &name);
while (NULL !=blocked->pcbnext)
{
if (blocked->pcbnext->https://www.wendangku.net/doc/2a12349231.html, == name) //阻塞队列中有要解除阻塞状态的进程,将进程放入就绪队列
{
if (NULL == header_running->pcbnext) //运行队列为空
{
if (NULL == header_ready->pcbnext) //就绪队列为空
{
header_running->pcbnext = blocked->pcbnext;
header_running->pcbnext->pcb.status = Running;
blocked->pcbnext = blocked->pcbnext->pcbnext;
break;
}
}
else
{
tail_ready->pcbnext = blocked->pcbnext; //放到就绪队列尾部
tail_ready = tail_ready->pcbnext;
tail_ready->pcb.status = Ready;
tail_ready->pcbnext = NULL;
blocked->pcbnext = blocked->pcbnext->pcbnext;
break;
}
}
}
if (NULL != blocked->pcbnext)
printf("没有该进程!!!\n");
}
/***运行-终止***/
void status5(void)
{
struct Exit *EXit = (struct Exit *)malloc(sizeof(struct Exit));
if (NULL == exit)
{
perror("error");
exit(1);
}
/***将终止的进程放入终止状态*/
EXit->id = header_running->pcbnext->pcb.id;
EXit->name = header_running->pcbnext->https://www.wendangku.net/doc/2a12349231.html,;
EXit->pcbnext = NULL;
tail_exit->pcbnext = EXit;
tail_exit = tail_exit->pcbnext;
/***回收终止了的进程的内存空间***/
struct Running *running = header_running->pcbnext;
header_running->pcbnext = NULL;
free(running);
}
void print(void)
{
struct Ready *ready = header_ready->pcbnext;
struct Blocked *blocked = header_blocked->pcbnext;
struct Exit *exit = header_exit->pcbnext;
printf("正在运行的进程是:\t");
if(NULL != header_running->pcbnext)
printf("%c", header_running->pcbnext->https://www.wendangku.net/doc/2a12349231.html,);
printf("\n");
printf("处于就绪状态的进程的有:\t");
while (NULL != ready)
{
printf("%c, ", ready->https://www.wendangku.net/doc/2a12349231.html,);
ready = ready->pcbnext;
}
printf("\n");
printf("处于阻塞状态的进程的有:\t");
while (NULL != blocked)
{
printf("%c, ", blocked->https://www.wendangku.net/doc/2a12349231.html,);
blocked = blocked->pcbnext;
}
printf("\n");
printf("处于终止状态的进程的有:\t");
while (NULL != exit)
{
printf("%c, ", exit->name);
exit = exit->pcbnext;
}
}
5.运行结果:
程序使用说明
0---创建进程 1---就绪-运行 2---运行-就绪 3---运行到阻塞 4---阻塞-就绪 5---运行-终止
实验一进程管理 一、目的 进程调度是处理机管理的核心内容。本实验要求编写和调试一个简单的进程调度程序。通过本实验加深理解有关进程控制块、进程队列的概念,并体会和了解进程调度算法的具体实施办法。 二、实验内容及要求 1、设计进程控制块PCB的结构(PCB结构通常包括以下信息:进程名(进程ID)、进程优先数、轮转时间片、进程所占用的CPU时间、进程的状态、当前队列指针等。可根据实验的不同,PCB结构的内容可以作适当的增删)。为了便于处理,程序中的某进程运行时间以时间片为单位计算。各进程的轮转时间数以及进程需运行的时间片数的初始值均由用户给定。 2、系统资源(r1…r w),共有w类,每类数目为r1…r w。随机产生n进程P i(id,s(j,k),t),0<=i<=n,0<=j<=m,0<=k<=dt为总运行时间,在运行过程中,会随机申请新的资源。 3、每个进程可有三个状态(即就绪状态W、运行状态R、等待或阻塞状态B),并假设初始状态为就绪状态。建立进程就绪队列。 4、编制进程调度算法:时间片轮转调度算法 本程序用该算法对n个进程进行调度,进程每执行一次,CPU时间片数加1,进程还需要的时间片数减1。在调度算法中,采用固定时间片(即:每执行一次进程,该进程的执行时间片数为已执行了1个单位),这时,CPU时间片数加1,进程还需要的时间片数减1,并排列到就绪队列的尾上。 三、实验环境 操作系统环境:Windows系统。 编程语言:C#。 四、实验思路和设计 1、程序流程图
2、主要程序代码 //PCB结构体 struct pcb { public int id; //进程ID public int ra; //所需资源A的数量 public int rb; //所需资源B的数量 public int rc; //所需资源C的数量 public int ntime; //所需的时间片个数 public int rtime; //已经运行的时间片个数 public char state; //进程状态,W(等待)、R(运行)、B(阻塞) //public int next; } ArrayList hready = new ArrayList(); ArrayList hblock = new ArrayList(); Random random = new Random(); //ArrayList p = new ArrayList(); int m, n, r, a,a1, b,b1, c,c1, h = 0, i = 1, time1Inteval;//m为要模拟的进程个数,n为初始化进程个数 //r为可随机产生的进程数(r=m-n) //a,b,c分别为A,B,C三类资源的总量 //i为进城计数,i=1…n //h为运行的时间片次数,time1Inteval为时间片大小(毫秒) //对进程进行初始化,建立就绪数组、阻塞数组。 public void input()//对进程进行初始化,建立就绪队列、阻塞队列 { m = int.Parse(textBox4.Text); n = int.Parse(textBox5.Text); a = int.Parse(textBox6.Text); b = int.Parse(textBox7.Text); c = int.Parse(textBox8.Text); a1 = a; b1 = b; c1 = c; r = m - n; time1Inteval = int.Parse(textBox9.Text); timer1.Interval = time1Inteval; for (i = 1; i <= n; i++) { pcb jincheng = new pcb(); jincheng.id = i; jincheng.ra = (random.Next(a) + 1); jincheng.rb = (random.Next(b) + 1); jincheng.rc = (random.Next(c) + 1); jincheng.ntime = (random.Next(1, 5)); jincheng.rtime = 0;
重庆大学 学生实验报告 实验课程名称操作系统原理 开课实验室DS1501 学院软件学院年级2013专业班软件工程2 班学生姓名胡其友学号20131802 开课时间2015至2016学年第一学期 总成绩 教师签名洪明坚 软件学院制
《操作系统原理》实验报告 开课实验室:年月日学院软件学院年级、专业、班2013级软件工 程2班 姓名胡其友成绩 课程名称操作系统原理 实验项目 名称 指导教师洪明坚 教师 评语教师签名:洪明坚年月日 1.实验目的: ?进入实验环境 –双击expenv/setvars.bat ?检出(checkout)EPOS的源代码 –svn checkout https://www.wendangku.net/doc/2a12349231.html,/svn/epos ?编译及运行 –cd epos/app –make run ?清除所有的临时文件 –make clean ?调试 –make debug ?在“Bochs Enhanced Debugger”中,输入“quit”退出调试 –调试指令,请看附录A 2.实验内容: ?编写系统调用“time_t time(time_t *loc)” –功能描述 ?返回从格林尼治时间1970年1月1日午夜起所经过的秒数。如果指针loc 非NULL,则返回值也被填到loc所指向的内存位置 –数据类型time_t其实就是long ?typedef long time_t; 3.实验步骤: ?Kernel space –K1、在machdep.c中,编写系统调用的实现函数“time_t sys_time()”,计算用户秒数。需要用到 ?变量g_startup_time,它记录了EPOS启动时,距离格林尼治时间1970年1午夜的秒数 ?变量g_timer_ticks
东北大学秦皇岛分校计算机与通信工程学院 计算机操作系统课程设计 设计题目:进程管理器 专业名称计算机科学与技术 班级学号xxxx 学生姓名xxxx 指导教师xxxxx 设计时间2014-12-29~2015-1-15
课程设计任务书 专业:计算机科学与技术学号:学生姓名(签名):设计题目 1、高优先权调度算法的模拟 2、进程管理器的模拟实现 二、主要内容 1、目的: 编程模拟实现进程管理器,加深对进程、程序概念掌握. 2、进程管理器 主界面如下: (1)源代码: <1> Form1.cs using System; using System.Collections.Generic; using https://www.wendangku.net/doc/2a12349231.html,ponentModel; using System.Data; using System.Drawing;
using System.Text; using System.Windows.Forms; using System.Management; using System.Diagnostics; namespace WindowsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); this.listProcesses.MultiSelect = false; this.listProcesses.View = View.Details; this.listProcesses.Columns.Add("pname",(int)CreateGraphics().MeasureString( "aaaaaaaaaaaaaaaaaaaaaa",Font).Width); this.listProcesses.Columns.Add("pID", (int)CreateGraphics().MeasureString( "000000000000", Font).Width); this.listProcesses.Columns.Add("username", (int)CreateGraphics().MeasureString( "aaaaaaaaaaaaaaaaaaaaa", Font).Width); this.listProcesses.Columns.Add("priority", (int)CreateGraphics().MeasureString( "aaaaaaaaa", Font).Width); this.listProcesses.Columns.Add("Memory usage", (int)CreateGraphics().MeasureString( "000000000000000",Font).Width); } private void Form1_Load(object sender, EventArgs e) { RefreshList(); } private void RefreshList() { Process[] processes; processes = Process.GetProcesses(); this.listProcesses.Items.Clear(); foreach (Process instance in processes) { ListViewItem lvi = new ListViewItem(instance.ProcessName); lvi.SubItems.Add(FormatProcessID(instance.Id)); lvi.SubItems.Add(GetProcessUserName(instance.Id)); lvi.SubItems.Add(instance.BasePriority.ToString());
中南大学信息科学与工程学院实验报告 姓名:安磊 班级:计科0901 学号: 0909090310
指导老师:宋虹
目录 课程设计内容 ----------------------------------- 3 uC/OS操作系统简介 ------------------------------------ 3 uC/OS操作系统的组成 ------------------------------ 3 uC/OS操作系统功能作用 ---------------------------- 4 uC/OS文件系统的建立 ---------------------------- 6 文件系统设计的原则 ------------------------------6 文件系统的层次结构和功能模块 ---------------------6 文件系统的详细设计 -------------------------------- 8 文件系统核心代码 --------------------------------- 9 课程设计感想 ------------------------------------- 11 附录-------------------------------------------------- 12
课程设计内容 在uC/OS操作系统中增加一个简单的文件系统。 要求如下: (1)熟悉并分析uc/os操作系统 (2)设计并实现一个简单的文件系统 (3)可以是存放在内存的虚拟文件系统,也可以是存放在磁盘的实际文件系统 (4)编写测试代码,测试对文件的相关操作:建立,读写等 课程设计目的 操作系统课程主要讲述的内容是多道操作系统的原理与技术,与其它计算机原理、编译原理、汇编语言、计算机网络、程序设计等专业课程关系十分密切。 本课程设计的目的综合应用学生所学知识,建立系统和完整的计算机系统概念,理解和巩固操作系统基本理论、原理和方法,掌握操作系统开发的基本技能。 I.uC/OS操作系统简介 μC/OS-II是一种可移植的,可植入ROM的,可裁剪的,抢占式的,实时多任务操作系统内核。它被广泛应用于微处理器、微控制器和数字信号处理器。 μC/OS 和μC/OS-II 是专门为计算机的嵌入式应用设计的,绝大部分代码是用C语言编写的。CPU 硬件相关部分是用汇编语言编写的、总量约200行的汇编语言部分被压缩到最低限度,为的是便于移植到任何一种其它的CPU 上。用户只要有标准的ANSI 的C交叉编译器,有汇编器、连接器等软件工具,就可以将μC/OS-II嵌入到开发的产品中。μC/OS-II 具有执行效率高、占用空间小、实时性能优良和可扩展性强等特点,最小内核可编译至2KB 。μC/OS-II 已经移植到了几乎所有知名的CPU 上。 严格地说uC/OS-II只是一个实时操作系统内核,它仅仅包含了任务调度,任务管理,时间管理,内存管理和任务间的通信和同步等基本功能。没有提供输入输出管理,文件系统,网络等额外的服务。但由于uC/OS-II良好的可扩展性和源码开放,这些非必须的功能完全 可以由用户自己根据需要分别实现。 uC/OS-II目标是实现一个基于优先级调度的抢占式的实时内核,并在这个内核之上提供最基本的系统服务,如信号量,邮箱,消息队列,内存管理,中断管理等。 uC/OS操作系统的组成 μC/OS-II可以大致分成核心、任务处理、时间处理、任务同步与通信,CPU的移植等5个部分。如下图:
操作系统实验报告——实验二:C编程环境 实验目的 1.熟悉Linux下C程序设计的环境; 2.对系统调用有初步了解。 实验内容 1.Linux下C语言程序的开发过程 a、在用户主目录下用vi编辑C语言源程序(源程序已附后),如:$vi hello.c。 b、用gcc编译C语言源程序:$gcc ./hello.c -o example 这里gcc是Linux下的C语言程序编译器(GNU C Compiler),./hello.c表示待编译的源文件是当前工作目录下的hello.c,-o example表示编译后产生的目标代码文件名为example。 c、若编译不正确,则进入vi修改源程序,否则,运行目标代码:$./example 。注意: 这只是gcc最基本的用法,其他常用选项有:-c , -S , -O , -O2, -g 等。 2.编辑、调试下面c语言程序,说明该程序的功能。 #include
实验1:熟悉Linux系统 一、题目:熟悉Linux系统 二、目的: 熟悉与掌握Linux系统基本命令,熟悉Linux编程环境,为以后的实验打下基础。 1、启动、退出、ls(显示目录内容)、cp(文件或目录的复制)、mv(文件、目录更名或移动)、rm(删除文件或目录)、mkdir(创建目录)、rmdir(删除空目录)、cd(改变工作目录)… 2、C语言编辑、编译 三、内容及要求: 1、熟练掌握Linux基本文件命令; 2、掌握Linux编辑程序、对源代码进行编译、连接、运行及调试的过程; 3、认真做好预习,书写预习报告; 4、实验完成后要认真总结、完成实验报告。 四、内容及要求: 在Linux环境下编制、调试源程序的实际过程(每一步的具体说明)。 实验2:进程状态 一、题目:进程状态 二、目的: 自行编制模拟程序,通过形象化的状态显示,使学生理解进程的概念、进程之间的状态转换及其所带来的PCB内容、组织的变化,理解进程与其PCB间的一一对应关系。 三、内容及要求 1、设计并实现一个模拟进程状态转换及其相应PCB组织结构变化的程序; 2、独立设计、编写、调试程序; 3、程序界面应能反映出在模拟条件下,进程之间状态转换及其对应的PCB组织的变化。 4、进程的状态模型(三状态、五状态、七状态或其它)可自行选择, 5、代码书写要规范,要适当地加入注释; 6、鼓励在实验中加入新的观点或想法,并加以实现;
7、认真进行预习,完成预习报告; 8、实验完成后,要认真总结,完成实验报告。 四、程序流程图 图4、1 进程转换流程五、使用的数据结构及其说明 struct PCB //进程控制块PCB { char name; //名字标识 string state; //状态 int time; //执行时间 }; typedef struct PCB ElemType; struct QNode { ElemType data; struct QNode *next; }; //链式队列结点 typedef struct QNode QNode; //结点 typedef struct QNode *PNode;
实时操作系统课程实验报告 专业:通信1001 学号:3100601025 姓名:陈治州 完成时间:2013年6月11日
实验简易电饭煲的模拟 一.实验目的: 掌握在基于嵌入式实时操作系统μC/OS-II的应用中,基于多任务的模式的编程方法。锻炼综合应用多任务机制,任务间的通信机制,内存管理等的能力。 二.实验要求: 1.按“S”开机,系统进入待机状态,时间区域显示当前北京时间,默认模式“煮饭”; 2.按“C”选择模式,即在“煮饭”、“煮粥”和“煮面”模式中循环选择; 3.按“B”开始执行模式命令,“开始”状态选中,时间区域开始倒计时,倒计时完成后进入“保温”状态,同时该状态显示选中,时间区域显示保温时间; 4.按“Q”取消当前工作状态,系统进入待机状态,时间区域显示北京时间,模式为当前模式; 5.按“X”退出系统,时间区域不显示。 6.煮饭时长为30,煮粥时长为50,煮面时长为40. 三.实验设计: 1.设计思路: 以老师所给的五个程序为基础,看懂每个实验之后,对borlandc的操作有了大概的认识,重点以第五个实验Task_EX为框架,利用其中界面显示与按键扫描以及做出相应的响应,对应实现此次实验所需要的功能。 本次实验分为界面显示、按键查询与响应、切换功能、时钟显示与倒计时模块,综合在一起实验所需功能。 2.模块划分图: (1)界面显示: Main() Taskstart() Taskstartdispinit() 在TaskStartDispInit()函数中,使用PC_DispStr()函数画出界面。
(2)按键查询与响应: Main() Taskstart() 在TaskStart()函数中,用if (PC_GetKey(&key) == TRUE)判断是否有按键输入。然后根据key 的值,判断输入的按键是哪一个;在响应中用switch语句来执行对应按键的响应。 (3)切换功能: l计数“C”按 键的次数 M=l%3 Switch(m) M=0,1,2对应于煮饭,煮粥,煮面,然后使用PC_DispStr()函数在选择的选项前画上“@”指示,同时,在其余两项钱画上“”以“擦出”之前画下的“@”,注意l自增。 四.主要代码: #include "stdio.h" #include "includes.h" #include "time.h" #include "dos.h" #include "sys/types.h" #include "stdlib.h" #define TASK_STK_SIZE 512 #define N_TASKS 2 OS_STK TaskStk[N_TASKS][TASK_STK_SIZE]; OS_STK TaskStartStk[TASK_STK_SIZE]; INT8U TaskData[N_TASKS];
HUNAN UNIVERSITY 操作系统实验报告
目录 一、内容 (3) 二、目的 (3) 三、实验设计思想和练习题 (3) 练习0:填写已有实验 (3) 练习1:实现 first-fit 连续物理内存分配算法(需要编程) (3) 练习2:实现寻找虚拟地址对应的页表项(需要编程) (8) 练习3:释放某虚地址所在的页并取消对应二级页表项的映射(需要编程) (11) 运行结果 (13) 四、实验体会 (13)
一、内容 本次实验包含三个部分。首先了解如何发现系统中的物理内存;然后了解如何建立对物理内存的初步管理,即了解连续物理内存管理;最后了解页表相关的操作,即如何建立页表来实现虚拟内存到物理内存之间的映射,对段页式内存管理机制有一个比较全面的了解。 二、目的 1.理解基于段页式内存地址的转换机制; 2.理解页表的建立和使用方法; 3.理解物理内存的管理方法。 三、实验设计思想和练习题 练习0:填写已有实验 使用eclipse中的diff/merge工具将实验1的代码填入本实验中代码中有“LAB1”的注释相应部分。 练习1:实现 first-fit 连续物理内存分配算法(需要编程) 在实现first fit 内存分配算法的回收函数时,要考虑地址连续的空闲块之间的合并操作。提示:在建立空闲页块链表时,需要按照空闲页块起始地址来排序,形成一个有序的链表。可能会修改default_pmm.c 中的default_init,default_init_memmap,default_alloc_pages, default_free_pages等相关函数。请仔细查看和理解default_pmm.c中的注释。 请在实验报告中简要说明你的设计实现过程。请回答如下问题: 你的first fit算法是否有进一步的改进空间。 解答: 分析思路: (1)数据结构: A.每个物理页利用一个Page结构体表示,查看kern/mm/memlayout.h包括:
操作系统实验报告班级物联网1302班 学号 姓名
实验 3 进程同步和通信-生产者和消费者问题模拟 1. 目的: 调试、修改、运行模拟程序,通过形象化的状态显示,使学生理解进程的概念,了解同步和通信的过程,掌握进程通信和同步的机制,特别是利用缓冲区进行同步和通信的过程。通过补充新功能,使学生能灵活运用相关知识,培养创新能力。 2. 内容及要求: 1) 调试、运行模拟程序。 2) 发现并修改程序中不完善的地方。 3) 修改程序,使用随机数控制创建生产者和消费者的过程。 4) 在原来程序的基础上,加入缓冲区的写互斥控制功能,模拟多个进程存取一个公共缓冲区,当有进程正在写缓冲区时,其他要访问该缓冲区的进程必须等待,当有进程正在读取缓冲区时,其他要求读取的进程可以访问,而要求写的进程应该等待。 5) 完成1) 、2) 、3)功能的,得基本分,完成4)功能的加2 分,有其它功能改进的再加2 分3. 程序说明: 本程序是模拟两个进程,生产者(producer)和消费者(Consumer)工作。生产者每次产生一个数据,送入缓冲区中。消费者每次从缓冲区中取走一个数据。缓冲区可以容纳8 个数据。因为缓冲区是有限的,因此当其满了时生产者进程应该等待,而空时,消费者进程应该等待;当生产者向缓冲区放入了一个数据,应唤醒正在等待的消费者进程,同样,当消费者取走一个数据后,应唤醒正在等待的生产者进程。就是生产者和消费者之间的同步。 每次写入和读出数据时,都将读和写指针加一。当读写指针同样时,又一起退回起点。当写指针指向最后时,生产者就等待。当读指针为零时,再次要读取的消费者也应该等待。 为简单起见,每次产生的数据为0-99 的整数,从0 开始,顺序递增。两个进程的调度是通过运行者使用键盘来实现的。 4. 程序使用的数据结构 进程控制块:包括进程名,进程状态和执行次数。缓冲区:一个整数数组。 缓冲区说明块:包括类型,读指针,写指针,读等待指针和写等待指针。 5. 程序使用说明 启动程序后,如果使用0键则运行一次生产者进程,使用'c'键则运行一次消费者进程。通过屏幕可以观察到两个进程的状态和缓冲区变化的情况。 6. 实验流程图 源程序 #include
评分: SHANGHAI UNIVERSITY 操作系统实验报告 学院计算机工程与科学 专业计算机科学与技术 学号 学生姓名
《计算机操作系统》实验一报告 实验一题目:操作系统的进程调度 姓名:张佳慧学号 :12122544 实验日期: 2015.1 实验环境: Microsoft Visual Studio 实验目的: 进程是操作系统最重要的概念之一,进程调度又是操作系统核心的主要内容。本实习要求学生独立地用高级语言编写和调试一个简单的进程调度程序。调度算法可任意选择或自行设计。例如,简单轮转法和优先数法等。本实习可加深对于进程调度和各种调度算法的理解。实验内容: 1、设计一个有n个进程工行的进程调度程序。每个进程由一个进程控制块(PCB)表示。进程控制块通常应包含下述信息:进程名、进程优先数、进程需要运行的时间、占用CPU的时间以及进程的状态等,且可按调度算法的不同而增删。 2、调度程序应包含2~3种不同的调度算法,运行时可任意选一种,以利于各种算法的分析比较。 3、系统应能显示或打印各进程状态和参数的变化情况,便于观察诸进程的调度过程。 操作过程: 1、本程序可选用优先数法或简单轮转法对五个进程进行调度。每个进程处于运行R(run)、就绪W(wait)和完成F(finish)三种状态之一,并假设起始状态都是就绪状态W。为了便于处理,程序进程的运行时间以时间片为单位计算。进程控制块结构如下: 进程控制块结构如下: PCB 进程标识数 链指针 优先数/轮转时间片数 占用 CPU 时间片数 进程所需时间片数 进程状态 进程控制块链结构如下:
其中:RUN—当前运行进程指针; HEAD—进程就绪链链首指针; TAID—进程就绪链链尾指针。2、算法与框图 (1) 优先数法。进程就绪链按优先数大小从高到低排列,链首进程首先投入运行。每过一个时间片,运行进程所需运行的时间片数减 1,说明它已运行了一个时间片,优先数也减 3,理由是该进程如果在一个时间片中完成不了,优先级应该降低一级。接着比较现行进程和就绪链链首进程的优先数,如果仍是现行进程高或者相同,就让现行进程继续进行,否则,调度就绪链链首进程投入运行。原运行进程再按其优先数大小插入就绪链,且改变它们对应的进程状态,直至所有进程都运行完各自的时间片数。 (2) 简单轮转法。进程就绪链按各进程进入的先后次序排列,进程每次占用处理机的轮转时间按其重要程度登入进程控制块中的轮转时间片数记录项(相当于优先数法的优先数记录项位置)。每过一个时间片,运行进程占用处理机的时间片数加 1,然后比较占用处理机的时间片数是否与该进程的轮转时间片数相等,若相等说明已到达轮转时间,应将现运行进程排到就绪链末尾,调度链首进程占用处理机,且改变它们的进程状态,直至所有进程完成各自的时间片。 (3) 程序框图
实验1:熟悉Linux系统 一、题目:熟悉Linux系统 二、目的: 熟悉和掌握Linux系统基本命令,熟悉Linux编程环境,为以后的实验打下基础。 1、启动、退出、ls(显示目录内容)、cp(文件或目录的复制)、mv(文件、目录更名或移动)、rm(删除文件或目录)、mkdir(创建目录)、rmdir(删除空目录)、cd(改变工作目录)… 2、C语言编辑、编译 三、内容及要求: 1、熟练掌握Linux基本文件命令; 2、掌握Linux编辑程序、对源代码进行编译、连接、运行及调试的过程; 3、认真做好预习,书写预习报告; 4、实验完成后要认真总结、完成实验报告。 四、内容及要求: 在Linux环境下编制、调试源程序的实际过程(每一步的具体说明)。 实验2:进程状态 一、题目:进程状态
二、目的: 自行编制模拟程序,通过形象化的状态显示,使学生理解进程的概念、进程之间的状态转换及其所带来的PCB内容、组织的变化,理解进程与其PCB间的一一对应关系。 三、内容及要求 1、设计并实现一个模拟进程状态转换及其相应PCB组织结构变化的程序; 2、独立设计、编写、调试程序; 3、程序界面应能反映出在模拟条件下,进程之间状态转换及其对应的PCB 组织的变化。 4、进程的状态模型(三状态、五状态、七状态或其它)可自行选择, 5、代码书写要规范,要适当地加入注释; 6、鼓励在实验中加入新的观点或想法,并加以实现; 7、认真进行预习,完成预习报告; 8、实验完成后,要认真总结,完成实验报告。 四、程序流程图
图4.1 进程转换流程五、使用的数据结构及其说明 struct PCB //进程控制块PCB { char name; //名字标识 string state; //状态 int time; //执行时间 }; typedefstruct PCB ElemType; structQNode { ElemType data; structQNode *next; }; //链式队列结点 typedefstructQNodeQNode; //结点 typedefstructQNode *PNode; typedefstruct { PNodefrnt; PNode rear;
嵌入式实时操作系统实验报告 任务间通信机制的建立 系别计算机与电子系 专业班级***** 学生姓名****** 指导教师 ****** 提交日期 2012 年 4 月 1 日
一、实验目的 掌握在基于嵌入式实时操作系统μC/OS-II的应用中,任务使用信号量的一般原理。掌握在基于优先级的可抢占嵌入式实时操作系统的应用中,出现优先级反转现象的原理及解决优先级反转的策略——优先级继承的原理。 二、实验内容 1.建立并熟悉Borland C 编译及调试环境。 2.使用课本配套光盘中第五章的例程运行(例5-4,例5-5,例5-6),观察运行结果,掌握信号量的基本原理及使用方法,理解出现优先级反转现象的根本原因并提出解决方案。 3.试编写一个应用程序,采用计数器型信号量(初值为2),有3个用户任务需要此信号量,它们轮流使用此信号量,在同一时刻只有两个任务能使用信号量,当其中一个任务获得信号量时向屏幕打印“TASK N get the signal”。观察程序运行结果并记录。 4. 试编写一个应用程序实现例5-7的内容,即用优先级继承的方法解决优先级反转的问题,观察程序运行结果并记录。 5.在例5-8基础上修改程序增加一个任务HerTask,它和YouTask一样从邮箱Str_Box里取消息并打印出来,打印信息中增加任务标识,即由哪个任务打印的;MyTask发送消息改为当Times为5的倍数时才发送,HerTask接收消息采用无等待方式,如果邮箱为空,则输出“The mailbox is empty”, 观察程序运行结果并记录。 三、实验原理 1. 信号量 μC/OS-II中的信号量由两部分组成:一个是信号量的计数值,它是一个16位的无符号整数(0 到65,535之间);另一个是由等待该信号量的任务组成的等待任务表。用户要在OS_CFG.H中将OS_SEM_EN开关量常数置成1,这样μC/OS-II 才能支持信号量。
操作系统教程 实 验 指 导 书 姓名: 学号: 班级:软124班 指导老师:郭玉华 2014年12月10日
实验一WINDOWS进程初识 1、实验目的 (1)学会使用VC编写基本的Win32 Consol Application(控制台应用程序)。 (2)掌握WINDOWS API的使用方法。 (3)编写测试程序,理解用户态运行和核心态运行。 2、实验内容和步骤 (1)编写基本的Win32 Consol Application 步骤1:登录进入Windows,启动VC++ 6.0。 步骤2:在“FILE”菜单中单击“NEW”子菜单,在“projects”选项卡中选择“Win32 Consol Application”,然后在“Project name”处输入工程名,在“Location”处输入工程目录。创建一个新的控制台应用程序工程。 步骤3:在“FILE”菜单中单击“NEW”子菜单,在“Files”选项卡中选择“C++ Source File”, 然后在“File”处输入C/C++源程序的文件名。 步骤4:将清单1-1所示的程序清单复制到新创建的C/C++源程序中。编译成可执行文件。 步骤5:在“开始”菜单中单击“程序”-“附件”-“命令提示符”命令,进入Windows“命令提示符”窗口,然后进入工程目录中的debug子目录,执行编译好的可执行程序: E:\课程\os课\os实验\程序\os11\debug>hello.exe 运行结果 (如果运行不成功,则可能的原因是什么?) : 有可能是因为DOS下路径的问题 (2)计算进程在核心态运行和用户态运行的时间 步骤1:按照(1)中的步骤创建一个新的“Win32 Consol Application”工程,然后将清单1-2中的程序拷贝过来,编译成可执行文件。 步骤2:在创建一个新的“Win32 Consol Application”工程,程序的参考程序如清单1-3所示,编译成可执行文件并执行。 步骤3:在“命令提示符”窗口中运行步骤1中生成的可执行文件,测试步骤2中可执行文件在核心态运行和用户态运行的时间。 E:\课程\os课\os实验\程序\os12\debug>time TEST.exe 步骤4:运行结果 (如果运行不成功,则可能的原因是什么?) : 因为程序是个死循环程序 步骤5:分别屏蔽While循环中的两个for循环,或调整两个for循环的次数,写出运行结果。 屏蔽i循环: 屏蔽j循环: _______________________________________________________________________________调整循环变量i的循环次数:
操作系统实验三 实验报告 姓名李旦兰学号20083308 班级软件0802 指导教师那俊 实验名称存储管理 开设学期2010 – 2011第一学期 评定成绩 评定人签字 评定日期 东北大学软件学院2010年11月
实验三_B 一.实验题目 用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程。(题目四)二.实验目的 (1)进一步认识虚拟存储器的工作原理; (2)进一步认识文件系统的内部功能以及内部实现; (3)深入理解操作系统中文件系统的理论知识,加深对教材中的重要算法的理解; (4)掌握操作系统的原理及实现方法,提高综合运用各专业课知识的能力。 三.实验内容以及要求 (1)设计一个支持n个用户的简单二级文件系统,每个用户可保存m个文件,用户在一次运行中只能打开一个文件; (2)采用二级或二级以上的多级文件目录管理; (3)对文件应设置存取控制保护方式,如“只能执行”、“允许读”、“允许写等”;(4)系统的外部特征应接近于真实系统,可设置下述文件操作命令:Login 用户登录;Dir 列出文件目录; Create 建立文件;Delete 删除文件; Read 读文件;Write 写文件;Open 打开文件; Close 关闭文件。 (5)通过键盘使用该文件系统,系统应显示操作命令的执行结果。 四.实验环境 操作系统:Windows 7 开发语言:VC++ 开发工具:Microsoft Visual C++ 2008 Express Edition 五.程序设计思想 通过阅读实验指导书,整理出实验大体的思路,确定实体以及它们之间的关系。实体关系有三张表(主文件目录,用户文件目录以及打开文件目录)、命令服务和用户构成。用户负责输入命令。命令服务实现命令检查以及调用相关模块执行相应的命令功能。 (1)主文件目录(MFD),包括用户名和文件目录指针; struct user MFD[1]={{"0",0}};//MFD(用户名文件目录指针) (2)用户文件目录(UFD),包括文件名、保护码以及文件长度; struct file UFD[10];//用户文件目录(UFD-文件名保护码文件长度) (3)打开文件目录(AFD),包括打开文件名、打开保护码以及读写指针。采用数组形式存储打开的文件,数组每个元素保存一个打开文件的信息 struct file AFD[5]={{"0",0,0,0},{"0",0,0,0},{"0",0,0,0},{"0",0,0,0},{"0",0,0,0}};//运行文件目录(AFD)——一次运行用户可以打开个文件 在此模拟文件管理系统中可以实现的操作有: (1)用户登录:login,用户通过登录从而使用系统功能; (2)创建文件:create,创建一个指定名字的新文件,即在目录中增加一项,不考虑
实验报告 实验课程名称:操作系统 实验地点:南主楼七楼机房 2018—2019学年(一)学期 2018年 9月至 2019 年 1 月 专业: 班级: 学号: 姓名: 指导老师:刘一男
实验一 实验项目:分时系统模拟 实验学时:2实验日期: 2018-10-25 成绩: 实验目的利用程序设计语言模拟分时系统中多个进程按时间片轮转调度算法进行进程调度的过程; 假设有五个进程A,B,C,D,E,它们的到达时间及要求服务的时间分别为:进程名 A B C D E 到达时间0 1 2 3 4 服务时间 4 3 4 2 4 时间片大小为1,利用程序模拟A,B,C,D,E五个进程按时间片轮转的调度及执行过程并计算各进程的周转时间及带权周转时间。 执行过程并计算各进程的周转时间及带权周转时间。 轮转调度:BDACE
(1)修改时间片大小为2,利用程序模拟A,B,C,D,E五个进程按时间片轮转的调度及执行过程并计算各进程的周转时间及带权周转时间。 轮转调度:ADBCE (2)修改时间片大小为4,利用程序模拟A,B,C,D,E五个进程按时间片轮转的调度及执行过程并计算各进程的周转时间及带权周转时间.
顺序:ABCDE 1、思考 时间片的大小对调度算法产生什么影响?对计算机的性能产生什么影响?答:通过对时间片轮转调度算法中进程最后一次执行时间片分配的优化,提出了一种改进的时间片轮转调度算法,该算法具有更好的实时性,同时减少了任务调度次数和进程切换次数,降低了系统开销,提升了CPU的运行效率,使操作系统的性能得到了一定的提高。 A B C D E 时间片为1 周转时间12 9 14 8 13 3 3 3.5 4 3.25 带权周转 时间 时间片为2 周转时间8 12 13 7 13 2 4 3.25 3.5 3.25 带权周转 时间 时间片为4 周转时间 4 6 9 10 13 1 2 2.25 5 3.25 带权周转 时间
操作系统实验报告 学院:计算机与通信工程学院 专业:计算机科学与技术 班级: 学号: 姓名: 指导教师: 成绩: 2014年 1 月 1 日
实验一线程的状态和转换(5分) 1 实验目的和要求 目的:熟悉线程的状态及其转换,理解线程状态转换与线程调度的关系。 要求: (1)跟踪调试EOS线程在各种状态间的转换过程,分析EOS中线程状态及其转换的相关源代码; (2)修改EOS的源代码,为线程增加挂起状态。 2 完成的实验内容 2.1 EOS线程状态转换过程的跟踪与源代码分析 (分析EOS中线程状态及其转换的核心源代码,说明EOS定义的线程状态以及状态转换的实现方法;给出在本部分实验过程中完成的主要工作,包括调试、跟踪与思考等) 1.EOS 准备了一个控制台命令“loop ”,这个命令的命令函数是 ke/sysproc.c 文件中的ConsoleCmdLoop 函数(第797行,在此函数中使用 LoopThreadFunction 函数(第755 行)创建了一个优先级为 8 的线程(后面简称为“loop 线程”),该线程会在控制台中不停的(死循环)输出该线程的ID和执行计数,执行计数会不停的增长以表示该线程在不停的运行。loop命令执行的效果可以参见下图: 2. 线程由阻塞状态进入就绪状态 (1)在虚拟机窗口中按下一次空格键。 (2)此时EOS会在PspUnwaitThread函数中的断点处中断。在“调试”菜单中选择“快速监视”,在快速监视对话框的表达式编辑框中输入表达式“*Thread”,然后点击“重新计算”按钮,即可查看线程控制块(TCB)中的信息。其中State域的值为3(Waiting),双向链表项StateListEntry的Next和Prev指针的值都不为0,说明这个线程还处于阻塞状态,并在某个同步对象的等待队列中;StartAddr域的值为IopConsoleDispatchThread,说明这个线程就是控制台派遣线程。 (3)关闭快速监视对话框,激活“调用堆栈”窗口。根据当前的调用堆栈,可以看到是由键盘中断服务程序(KdbIsr)进入的。当按下空格键后,就会发生键盘中断,从而触发键盘中断服务程序。在该服务程序的最后中会唤醒控制台派遣线程,将键盘事件派遣到活动的控制台。 (4)在“调用堆栈”窗口中双击PspWakeThread函数对应的堆栈项。可以看到在此函数中连续调用了PspUnwaitThread函数和PspReadyThread函数,从而使处于阻塞状态的控制台派遣线程进入就绪状态。 (5)在“调用堆栈”窗口中双击PspUnwaitThread函数对应的堆栈项,先来看看此函数是如何改变线程状态的。按F10单步调试直到此函数的最后,然后再从快速监视对
操作系统实验一 姓名: 学号: 专业:计算机科学与技术 第一步:目录和文件组织 在您的home目录下有一系列的文件,您决定到时间整理一下了.您计划生成一些新的子目录,然后根据您的计划拷贝和移动这些文件到适当的目录;另外,这些文件不是都有用的,有一些是要删除掉的。 任务: 1.以用户名root密码123456配额的在tty1上登陆。 2.在您登陆系统以后,你将进入您的home目录.你可以使用"打印工作目录"检查这一情况 $ pwd /home/root 3.使用如下每条命令检查您是否还有文件在您的home目录下: $ ls$ ls -a$ ls –al 为什么第一和第二条命令返回不同的文件数? 第三条命令返回的在您当前的home目录下最大的文件是多少?46996
您的home目录下有子目录吗?没有 4.您现在使用touch为以后的步骤建立文件。这种扩展在接下来的命令中是如何工作的,在以后的章节中进行讨论。现在,仅仅按照下面的行键入就行了(在集合与集合之间使用包括花括号{}和下划线的字符) $ touch {report,memo,graph}_{sep,oct,nov,dec}_{a,b,c}{1,2,3}
5.使用命令ls检查最后一条命令的结果,你会发现它在您的home目录下生成了108个新的空文件(您不必数)。这些文件代表了您将使用的在这个步骤中的代表的数据文件。如果没有这些文件,该试验后面的步骤就无法进行。 6.为了组织您的文件,您必须先建立一些新目录,使用mkdir在您的home 目录中直接 建立一些子目录: $ mkdir a_reports $ mkdir september october november december 再使用ls 检查您的工作。