概述
实验一 几种操作系统的界面
一、目的和要求
- 目的
本实验的目的是使学生熟悉1—2种操作系统的界面,在熟练使用机器的基础上,能了解各种操作命令和系统调用在系统中的大致工作过程。也就是通过操作系统的外部特征,逐步深入到操作系统的内部实质内容中去。
- 要求
- 能熟练的在1—2种操作系统的环境下工作,学会使用各种命令,熟悉系统提供的各种功能,主动而有效地使用计算机。
- 熟悉系统实用程序的调用方法和各种系统调用模块的功能和作用
二、内容
在某种操作系统的环境下建立、修改、运行、打印源程序和结果,最后撤消一个完整的程序。
提示:可按下述步骤进行
- 编写一个完整的源程序,通过编辑命令送入机器,建立源程序文件;
- 编译该源文件,建立相应的目标文件;
- 编译有错时,再用编辑命令修改源文件,消除全部词法和语法错误;
- 连接目标文件,形成可执行文件;
- 执行该文件,得到结果;
- 打印输出源程序和运行结果;
- 撤消本次实验中形成的所有文件。
三、实验步骤及程序流程图
1.建立工作路径
mkdir zhou
新建目录
dir
显示当前目录下的所有文件信息
2.编写源文件
- 将文件的扩展名改成Homework.java,然后编译形成java字节码文件。
Javac Homework.java
- 运行java文件
java Homework
- 认识ubuntu操作系统
- java程序编译运行过程
四、程序清单
Java源代码
import java.awt.Choice;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.Border;
public class Homework {
public static void main(String[] args) {
new MyFrame("周大哥的购物车").load();
}
}
class MyFrame extends JFrame {
JButton b1;
JButton b2;
JButton b3;
JButton b4;
JPanel p1;
JPanel p2;
JPanel p3;
Vector<String> vLeft;
Vector<String> vRight;
JList j2;
JList j1;
MyFrame(String name) {
// this.setBackground(Color.BLUE);
this.setTitle(name);
// this.setIconImage(new );
b1 = new JButton(">>");
// b1.setContentAreaFilled(false);
b1.setBorder(BorderFactory.createRaisedBevelBorder());
b2 = new JButton(">");
b2.setBorder(BorderFactory.createRaisedBevelBorder());
b3 = new JButton("<<");
b3.setBorder(BorderFactory.createRaisedBevelBorder());
b4 = new JButton("<");
b4.setBorder(BorderFactory.createRaisedBevelBorder());
p1 = new JPanel();
p1.setBackground(Color.PINK);
//p1.setPreferredSize(new Dimension(300, 800));
b2.addMouseListener(new Mon1());
b4.addMouseListener(new Mon1());
b1.addMouseListener(new Mon2());
b3.addMouseListener(new Mon2());
// 中间的面板设置4行1列
p2 = new JPanel(new GridLayout(4, 1, 0, 20));
p2.setBackground(Color.red);
p3 = new JPanel();
p3.setBackground(Color.PINK);
p3.setBounds(100, 100, 400, 500);
vRight = new Vector<String>();
vRight.add("书");
vRight.add("笔");
vRight.add("橡皮");
vRight.add("眼镜");
vRight.add("手机");
vLeft = new Vector<String>();
vLeft.add("羽绒服");
vLeft.add("裤子");
vLeft.add("衬衣");
vLeft.add("运动鞋");
vLeft.add("背包");
vLeft.add("球拍");
j1 = new JList(vLeft);
//j1.setPreferredSize(new Dimension(80,10 ));
j1.setFont(new Font("宋体", Font.BOLD + Font.ITALIC, 30));
j1.setSelectionBackground(Color.yellow);
j2 = new JList(vRight);
j2.setFont(new Font("宋体", Font.BOLD + Font.ITALIC, 30));
j2.setSelectionBackground(Color.yellow);
//j2.setPreferredSize(new Dimension(100, 8));
}
void load() {
this.setLayout(new FlowLayout(FlowLayout.CENTER, 50, 50));
j1.add(b1);
j1.setVisibleRowCount(10);
p1.add(new JScrollPane(j1));
add(p1);
// 在面板內添加按鈕
p2.add(b1);
p2.add(b2);
p2.add(b3);
p2.add(b4);
add(p2);
// p3.add(t2);
j2.setVisibleRowCount(10);
p3.add(new JScrollPane(j2));
add(p3);
pack();
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
}
class Mon2 implements MouseListener {
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
JButton button = (JButton) e.getSource();
if (button.getText().equals(">>")) {
vRight.addAll(vLeft);
vLeft.clear();
// System.out.println("我执行了");
} else {
vLeft.addAll(vRight);
vRight.clear();
}
j1.updateUI();
j2.updateUI();
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
}
class Mon1 implements MouseListener {
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
// TODO Auto-generated method stub
JButton t = (JButton) e.getSource();
// 向右移动
if (t.getText().equals(">")) {
int num[] = j1.getSelectedIndices();
if (num.length == 0 || vLeft.size() == 0) {
JOptionPane.showMessageDialog(null, "亲,请选择选项后移动");
} else if (num.length >= 1) {
Vector<String> temp = new Vector<String>();
for (int i : num) {
// if((vLeft.get(i))!=null)
temp.add(vLeft.get(i));
}
for (String i : temp) {
vLeft.remove(i);
vRight.add(i);
}
}
} // 向左移动
else if (t.getText().equals("<")) {
int num[] = j2.getSelectedIndices();
Vector<String> temp = new Vector<String>();
if (num.length == 0 || vRight.size() == 0) {
JOptionPane.showMessageDialog(null, "亲,请选择好后移动");
} else {
for (int i : num) {
// if((vRight.get(i))!=null)
temp.add(vRight.get(i));
}
for (String aa : temp) {
vRight.remove(aa);
vLeft.add(aa);
}
}
}
j2.updateUI();
j1.updateUI();
j1.setSelectedIndex(0);
j2.setSelectedIndex(0);
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
}
}
五、心得体会
实践是检验真理的唯一标准,通过对目前市场上的windows和ubuntu操作系统的认识,让我对操作系统有了新的理解和应用。Ubuntu系统有以下几方面的优点:
1.高效的文件管理系统,一般情况下不需要碎片整理
2.产生的系统垃圾很少,系统不会随着使用时间的增多而越来越卡
3.拷贝文件速度快,Win10达到5M/S,Ubuntu达到20M/S
4.系统安全稳定,漏洞修复快,极少中病毒
5.权限管理很严格,避免用户误操作
6.DIY界面,改善用户体验,自由度高(对UI有追求的同学可尽情折腾)
7.强大的命令行,基本上所有操作可在上面执行(瞬间逼格升几个Lev)
8.无软件捆绑行为,桌面无广告弹窗行为
9.无盗版系统这一说法,开源免费正版
而Windows10的优点如下:
1.软件多,软件多,软件多(重要的事情说三遍)
2.操作方式对电脑小白友好,上手快 。
3.使用普及率高,同事间协助合作方便。.
4.Win10针对Modern应用进行优化,提升用户体验(界面简洁,运行流畅,去除少用功能,保留核心有用的功能,安装包体积小) 。
5.支持大量驱动,充分发挥硬件性能。
在实际开发中,应当按照自己的项目需求来恰当选择。文字/命令行界面虽然没有图形界面美观,但操作响应速度快,执行稳定,不容易出错。
实验二 进程调度程序设计
一、目的和要求
- 目的
进程是操作系统最重要的概念之一,进程调度是操作系统的主要内容,本实验要求学生独立地用高级语言编写一个进程调度程序,调度算法可任意选择或自行设计,本实验可使学生加深对进程调度和各种调度算法的理解。
- 要求
- 设计一个有几个进程并发执行的进程调度程序,每个进程由一个进程控制块(PCB)表示,进程控制块通常应包括下述信息:进程名,进程优先数,进程需要运行的时间,占用CPU的时间以及进程的状态等,且可按照调度算法的不同而增删。
- 调度程序应包含2—3种不同的调度算法,运行时可以任选一种,以利于各种方法的分析和比较。
- 系统应能显示或打印各进程状态和参数的变化情况,便于观察。
二、示例
- 题目 本程序可选用优先数法或简单轮转法对五个进程进行调度。每个进程处于运行R(run)、就绪W(wait)和完成F(finish)三种状态之一,并假定起始状态都是就绪状态W。
为了便于处理,程序中进程的运行时间以时间片为单位计算。各进程的优先数或轮转时间片数、以及进程需要运行的时间片数,均由伪随机数发生器产生。
进程控制块结构如表2-1所示:
表2-1PCB
进程标识符 |
链指针 |
优先数/轮转时间片数 |
占用CPU时间片数 |
进程所需时间片数 |
进程状态 |
进程控制块链结构如图2-1所示:
RUN HEAD TAIL
1 |
┇ |
R |
3 |
┇ |
W |
5 |
┇ |
W |
W |
0 |
┇ |
2 |
…
图2-1 进程控制块链结构
其中:RUN—当前运行进程指针;
HEAD—进程就绪链链首指针;
TAIL—进程就绪链链尾指针。
2. 算法与框图程序框图如图2-2所示。
priority |
是 |
输入调度算法alog |
开始 |
alog=priority/round robin? |
生成并按优先数大小排列进程控制块链 |
进程时间片数为0? |
从链首取一个进程投入运行 |
生成并按进入次序 排列进程控制块链 |
链首进程投入运行 |
时间片到,进程时间片 数减1,优先数减3 |
运行进程退出,排到进程链尾部 |
撤消该进程 |
链首进程投入运行 |
时间片到,进程时间片数 减1,占用CPU时间加1 |
优先数大于链首进程? |
进程时间片数为0? |
撤消该进程 |
运行进程退出,按优先数插入进程链 |
从链首取一个进程投入运行 |
结束 |
结束 |
进程队列空? |
进程队列空? |
是 |
是 |
是 |
否 |
否 |
否 |
否 |
否 |
是 |
round robin |
占用处理机时间片到? |
否 |
是 |
图2-2 进程调度框图
(1)优先数法。 进程就绪链按优先数大小从大到小排列,链首进程首先投入运行。每过一个时间片,运行进程所需运行的时间片数减1,说明它已运行了一个时间片,优先数也减3。理由是该进程如果在一个时间片中完成不了,优先级应降低一级。接着比较现行进程和就绪链链首进程的优先数,如果仍是现行进程高或者相同,就让现行进程继续运行,否则,调度就绪链链首进程投入运行。原运行进程再按其优先数大小插入就绪链,且改变它们对应的进程状态,直至所有进程都运行完各自的时间片数。
(2)简单轮转法。 进程就绪链按各进程进入的先后次序排列,链首进程首先投入运行。进程每次占用处理机的轮转时间按其重要程度登入进程控制块中的轮转时间片数记录项(相应于优先数法的优先数记录项位置)。每过一个时间片,运行进程占用处理机的时间片数加1,然后比较占用处理机的时间片数是否与该进程的轮转时间片数相等,若相等说明已到达轮转时间,应将现运行进程排到就绪链末尾,调度链首进程占用处理机,且改变它们的进程状态,直至所有进程完成各自的时间片。
三、实验代码:
#include<iostream>
#include<string>
#include<time.h>
using namespace std;
int n;
class PCB
{
public:
int priorityNumber;//进程优先数
int occupy;//进程运行CPU时间
int pieceOftime;//轮转时间片
int need;//还需要时间
int Counter;
string processName;//进程名
string state;//进程状态
PCB * next;
};
PCB * run = NULL;
PCB * ready = NULL;
PCB * finish = NULL;
PCB * tial = ready;
void Dtime(int t);
void Prinft(int a)
{
if(a==1)
{
cout<<" 进程"<<"t"<<"优先数"<<"t"<<"还需要时间"<<"t"<<"已运行时间"<<"t"<<"状态:"<<endl;
}
else
cout<<" 进程"<<"t"<<"已运行时间"<<"t"<<"还需要时间"<<"t"<<"计数器"<<"t"<<"时间片"<<"t"<<"状态"<<endl;
}
void Prinft(int b,PCB * p)
{
if(b==1)
{
cout<<p->processName<<"tt"<<p->priorityNumber<<"t"<<p->need<<"tt"<<p->occupy<<"tt"<<p->state<<endl;
}
else
cout<<p->processName<<"tt"<<p->occupy<<"tt"<<p->need<<"tt"<<p->Counter<<"t"<<p->pieceOftime<<"t"<<p->state<<endl;
}
void display(int c)
{
PCB *p;
if(run!=NULL)
Prinft(c,run);
//Dtime(2);
p=ready;
while(p!=NULL)
{
Prinft(c,p);
p=p->next;
}
//Dtime(2);
p=finish;
while(p!=NULL)
{
Prinft(c,p);
p=p->next;
}
}
void insert(PCB *p)//插入就绪队列按Pri大小
{
PCB *S1,*S2;
if(ready==NULL)
{
p->next = NULL;
ready = p;
}
else
{
S1 = ready;
S2 = S1;
while(S1!=NULL)
{
if(S1->priorityNumber >= p->priorityNumber)
{
S2 = S1;
S1 = S1->next;
}
else
break;
}
if(S2->priorityNumber >= p->priorityNumber)
{
S2->next = p;
p->next = S1;
}
else
{
p->next = ready;
ready = p;
}
}
}
bool CTProcessOfPri()
{
PCB * Node;
cout <<"请输入创建进程的数目:"<<endl;
cin >>n;
for(int j = 0;j < n; j++)
{
Node = new PCB;
if(Node==NULL)
return false;
else
{
cout <<"亲,请输入进程的名称,进程需CPU时间例如:process 45"<<endl;
cin >>Node->processName>>Node->need;
Node->occupy = 0;
Node->state ="就绪态";
Node->priorityNumber =Node->need;
cout <<"进程"<<Node->processName<<"创建完毕!"<<endl;
}
insert(Node);
}
return true;
}
void priorityNumberority(int i)
{
run = ready;
ready = ready->next;
run->state = "运行态";
Prinft(i);
while(run!=NULL)
{
run->occupy=run->occupy+1;
run->need=run->need-1;
run->priorityNumber=run->priorityNumber-1;
if(run->need==0)
{
run->state = "完成";
run->next = finish;
finish = run;
run=NULL;
if(ready!=NULL)
{
run = ready;
run->state = "运行态";
ready = ready->next;
}
}
else if((ready!=NULL)&&(run->priorityNumber<ready->priorityNumber))
{
run->state="就绪态";
insert(run);
run = ready;
run->state = "运行态";
ready = ready->next;
}
display(i);
}
}
void queue(PCB *p)
{
if(ready==NULL)
{
p->next = NULL;
ready = p;
tial = p;
}
else
{
tial->next = p;
tial = p;
p->next = NULL;
}
}
bool CTProcessOfRuntime()
{
PCB * Node;
int m;
cout <<"请输入创建进程的数目:"<<endl;
cin >>n;
cout <<"输入时间片:"<<endl;
cin >>m;
for(int j = 0;j < n; j++)
{
Node = new PCB;
if(Node==NULL)
return false;
else
{
cout <<"亲,请输入进程的名称,进程需CPU时间例如:process 8"<<endl;
cin >>Node->processName>>Node->need;
Node->occupy = 0;
Node->state ="就绪态";
Node->Counter = 0;
Node->pieceOftime = m;
cout <<"进程"<<Node->processName<<"创建完毕!"<<endl;
}
queue(Node);
}
return true;
}
void Runtime(int c)
{
run = ready;
ready = ready->next;
run->state = "运行态";
Prinft(c);
while(run!=NULL)
{
run->occupy=run->occupy+1;
run->need=run->need-1;
run->Counter = run->Counter + 1;
if(run->need==0)
{
run->state = "完成";
run->next = finish;
finish = run;
run = NULL;
if(ready!=NULL)
{
run = ready;
ready = ready->next;
}
}
else if(run->Counter == run->pieceOftime)
{
run->Counter = 0;
run->state = "就绪态";
queue(run);
run=NULL;
if(ready!=NULL)
{
run = ready;
run->state = "运行态";
ready = ready->next;
}
}
display(c);
}
}
int main()
{
string i="";
cout <<" 功能选项:"<<endl;
cout <<"q键退出"<<endl;
cout <<"输入p选择优先数调度算法"<<endl;
cout <<"输入x选择循环时间片轮转算法"<<endl;
cin >>i;
if(i=="p") {
CTProcessOfPri();
priorityNumberority(1);
}
else if(i=="x"){
CTProcessOfRuntime();
Runtime(2);
}
else if(i=="q"){
return 0;
}
}
void Dtime(int t)
{
time_t current_time;
time_t start_time;
time(&start_time);
do
{
time(& current_time);
}while((current_time-start_time)<t);
}
/*
1.优先数调度算法
5
a 3
b 2
c 10
d 4
e 8
2.循环时间片轮转算法
5
10
a 3
b 2
c 10
d 4
e 8
*/
四、实验结果:
优先数调度
进程 优先数 还需要时间 已运行时间 状态:
c 9 9 1 运行态
e 8 8 0 就绪态
d 4 4 0 就绪态
a 3 3 0 就绪态
b 2 2 0 就绪态
c 8 8 2 运行态
e 8 8 0 就绪态
d 4 4 0 就绪态
a 3 3 0 就绪态
b 2 2 0 就绪态
e 8 8 0 运行态
c 7 7 3 就绪态
d 4 4 0 就绪态
a 3 3 0 就绪态
b 2 2 0 就绪态
e 7 7 1 运行态
c 7 7 3 就绪态
d 4 4 0 就绪态
a 3 3 0 就绪态
b 2 2 0 就绪态
c 7 7 3 运行态
e 6 6 2 就绪态
d 4 4 0 就绪态
a 3 3 0 就绪态
b 2 2 0 就绪态
c 6 6 4 运行态
e 6 6 2 就绪态
d 4 4 0 就绪态
a 3 3 0 就绪态
b 2 2 0 就绪态
e 6 6 2 运行态
c 5 5 5 就绪态
d 4 4 0 就绪态
a 3 3 0 就绪态
b 2 2 0 就绪态
e 5 5 3 运行态
c 5 5 5 就绪态
d 4 4 0 就绪态
a 3 3 0 就绪态
b 2 2 0 就绪态
c 5 5 5 运行态
d 4 4 0 就绪态
e 4 4 4 就绪态
a 3 3 0 就绪态
b 2 2 0 就绪态
c 4 4 6 运行态
d 4 4 0 就绪态
e 4 4 4 就绪态
a 3 3 0 就绪态
b 2 2 0 就绪态
d 4 4 0 运行态
e 4 4 4 就绪态
a 3 3 0 就绪态
c 3 3 7 就绪态
b 2 2 0 就绪态
e 4 4 4 运行态
a 3 3 0 就绪态
c 3 3 7 就绪态
d 3 3 1 就绪态
b 2 2 0 就绪态
e 3 3 5 运行态
a 3 3 0 就绪态
c 3 3 7 就绪态
d 3 3 1 就绪态
b 2 2 0 就绪态
a 3 3 0 运行态
c 3 3 7 就绪态
d 3 3 1 就绪态
b 2 2 0 就绪态
e 2 2 6 就绪态
c 3 3 7 运行态
d 3 3 1 就绪态
b 2 2 0 就绪态
e 2 2 6 就绪态
a 2 2 1 就绪态
d 3 3 1 运行态
b 2 2 0 就绪态
e 2 2 6 就绪态
a 2 2 1 就绪态
c 2 2 8 就绪态
d 2 2 2 运行态
b 2 2 0 就绪态
e 2 2 6 就绪态
a 2 2 1 就绪态
c 2 2 8 就绪态
b 2 2 0 运行态
e 2 2 6 就绪态
a 2 2 1 就绪态
c 2 2 8 就绪态
d 1 1 3 就绪态
e 2 2 6 运行态
a 2 2 1 就绪态
c 2 2 8 就绪态
d 1 1 3 就绪态
b 1 1 1 就绪态
a 2 2 1 运行态
c 2 2 8 就绪态
d 1 1 3 就绪态
b 1 1 1 就绪态
e 1 1 7 就绪态
c 2 2 8 运行态
d 1 1 3 就绪态
b 1 1 1 就绪态
e 1 1 7 就绪态
a 1 1 2 就绪态
c 1 1 9 运行态
d 1 1 3 就绪态
b 1 1 1 就绪态
e 1 1 7 就绪态
a 1 1 2 就绪态
d 1 1 3 运行态
b 1 1 1 就绪态
e 1 1 7 就绪态
a 1 1 2 就绪态
c 0 0 10 完成
b 1 1 1 运行态
e 1 1 7 就绪态
a 1 1 2 就绪态
d 0 0 4 完成
c 0 0 10 完成
e 1 1 7 运行态
a 1 1 2 就绪态
b 0 0 2 完成
d 0 0 4 完成
c 0 0 10 完成
a 1 1 2 运行态
e 0 0 8 完成
b 0 0 2 完成
d 0 0 4 完成
c 0 0 10 完成
a 0 0 3 完成
e 0 0 8 完成
b 0 0 2 完成
d 0 0 4 完成
c 0 0 10 完成
循环时间片轮转
进程 已运行时间 还需要时间 计数器 时间片 状态
a 1 2 1 10 运行态
b 0 2 0 10 就绪态
c 0 10 0 10 就绪态
d 0 4 0 10 就绪态
e 0 8 0 10 就绪态
a 2 1 2 10 运行态
b 0 2 0 10 就绪态
c 0 10 0 10 就绪态
d 0 4 0 10 就绪态
e 0 8 0 10 就绪态
b 0 2 0 10 就绪态
c 0 10 0 10 就绪态
d 0 4 0 10 就绪态
e 0 8 0 10 就绪态
a 3 0 3 10 完成
b 1 1 1 10 就绪态
c 0 10 0 10 就绪态
d 0 4 0 10 就绪态
e 0 8 0 10 就绪态
a 3 0 3 10 完成
c 0 10 0 10 就绪态
d 0 4 0 10 就绪态
e 0 8 0 10 就绪态
b 2 0 2 10 完成
a 3 0 3 10 完成
c 1 9 1 10 就绪态
d 0 4 0 10 就绪态
e 0 8 0 10 就绪态
b 2 0 2 10 完成
a 3 0 3 10 完成
c 2 8 2 10 就绪态
d 0 4 0 10 就绪态
e 0 8 0 10 就绪态
b 2 0 2 10 完成
a 3 0 3 10 完成
c 3 7 3 10 就绪态
d 0 4 0 10 就绪态
e 0 8 0 10 就绪态
b 2 0 2 10 完成
a 3 0 3 10 完成
c 4 6 4 10 就绪态
d 0 4 0 10 就绪态
e 0 8 0 10 就绪态
b 2 0 2 10 完成
a 3 0 3 10 完成
c 5 5 5 10 就绪态
d 0 4 0 10 就绪态
e 0 8 0 10 就绪态
b 2 0 2 10 完成
a 3 0 3 10 完成
c 6 4 6 10 就绪态
d 0 4 0 10 就绪态
e 0 8 0 10 就绪态
b 2 0 2 10 完成
a 3 0 3 10 完成
c 7 3 7 10 就绪态
d 0 4 0 10 就绪态
e 0 8 0 10 就绪态
b 2 0 2 10 完成
a 3 0 3 10 完成
c 8 2 8 10 就绪态
d 0 4 0 10 就绪态
e 0 8 0 10 就绪态
b 2 0 2 10 完成
a 3 0 3 10 完成
c 9 1 9 10 就绪态
d 0 4 0 10 就绪态
e 0 8 0 10 就绪态
b 2 0 2 10 完成
a 3 0 3 10 完成
d 0 4 0 10 就绪态
e 0 8 0 10 就绪态
c 10 0 10 10 完成
b 2 0 2 10 完成
a 3 0 3 10 完成
d 1 3 1 10 就绪态
e 0 8 0 10 就绪态
c 10 0 10 10 完成
b 2 0 2 10 完成
a 3 0 3 10 完成
d 2 2 2 10 就绪态
e 0 8 0 10 就绪态
c 10 0 10 10 完成
b 2 0 2 10 完成
a 3 0 3 10 完成
d 3 1 3 10 就绪态
e 0 8 0 10 就绪态
c 10 0 10 10 完成
b 2 0 2 10 完成
a 3 0 3 10 完成
e 0 8 0 10 就绪态
d 4 0 4 10 完成
c 10 0 10 10 完成
b 2 0 2 10 完成
a 3 0 3 10 完成
e 1 7 1 10 就绪态
d 4 0 4 10 完成
c 10 0 10 10 完成
b 2 0 2 10 完成
a 3 0 3 10 完成
e 2 6 2 10 就绪态
d 4 0 4 10 完成
c 10 0 10 10 完成
b 2 0 2 10 完成
a 3 0 3 10 完成
e 3 5 3 10 就绪态
d 4 0 4 10 完成
c 10 0 10 10 完成
b 2 0 2 10 完成
a 3 0 3 10 完成
e 4 4 4 10 就绪态
d 4 0 4 10 完成
c 10 0 10 10 完成
b 2 0 2 10 完成
a 3 0 3 10 完成
e 5 3 5 10 就绪态
d 4 0 4 10 完成
c 10 0 10 10 完成
b 2 0 2 10 完成
a 3 0 3 10 完成
e 6 2 6 10 就绪态
d 4 0 4 10 完成
c 10 0 10 10 完成
b 2 0 2 10 完成
a 3 0 3 10 完成
e 7 1 7 10 就绪态
d 4 0 4 10 完成
c 10 0 10 10 完成
b 2 0 2 10 完成
a 3 0 3 10 完成
e 8 0 8 10 完成
d 4 0 4 10 完成
c 10 0 10 10 完成
b 2 0 2 10 完成
a 3 0 3 10 完成
--------------------------------
Process exited after 14.68 seconds with return value 0
请按任意键继续. . .
五、心得体会:
纸上得来终觉浅,总得要实践一把才印象深刻,对上课所学知识才能真正理解消化。为了能使程序并发的执行,并且可以对并发执行的程序加以控制,引入进程。为了使参与并发执行的每个程序都能独立运行,为每个进程配置一个进程控制块PCB,用PCB来描述进程的基本情况和活动过程,进而控制和管理进程。这样由程序段、相关的数据段和PCB三部分构成了进程实体。进程是程序的一次执行。
进程是一个程序及其数据在处理上顺序执行时所发生的的活动。
进程是具有独立功能的程序在一个数据集合上运行的过程它是系统进行资源分配的独立单位。进程是一个资源的拥有者,如果频繁的进行创建撤销切换会造成很大的时空开销。所以,引入线程,将线程作为调度和分派的基本单位,进程作为资源分配的独立单位。各种调度算法之间的灵活使用对于操作系统的快速、稳定地执行具有重要的意义。
实验三 存储管理程序设计
一、目的和要求
- 目的
存储管理的主要功能之一是合理地分配主存空间。请求页式管理是一种常用的虚拟存储管理技术。
本实验的目的是通过请求页式存储管理中页面置换算法的模拟设计,来了解虚拟存储技术的特点,掌握请求页式存储管理的页面置换算法。
- 要求
模拟页式虚拟存储管理中硬件的地址转换和缺页中断的处理过程,并用先进先出调度算法(FIFO)处理缺页中断。
二、提示
- 为了装入一个页面而必须调出一页时,如果被选中调出的页面在执行中没有修改过,则不必把该页重新写到磁盘上(因磁盘上已有副本)。因此,在页表中可以增加是否修改过的标志,当执行“存”指令、“写”指令时把对应页的修改标志置成“1”,表示该页修改过,否则为“0”,表示该页未修改过。页表格式如表3-1所示。
表3-1 页表格式
页 号 | 标 志 | 主存块号 | 修改标志 | 磁盘上的位置 |
|
|
|
|
|
- 设计一个地址转换程序来模拟硬件的地址转换和缺页中断处理过程。当访问的页在主存时则形成绝对地址,但不去模拟指令的执行,可用输出转换后的绝对地址来表示一条指令已完成。当访问的页不在主存时则输出“*该页页号”来表示硬件产生了一次缺页中断。模拟地址转换的程序流程如图3-1所示。
- 编制一个FIFO页面调度程序。FIFO页面调度算法总是先调出作业中最先进入主存的那一页,因此,可以用一个数组来构成页号队列。数组中每个元素是该作业已在主存的页面号,假定分配给作业的主存块数为m,且该作业开始的m页已装入主存,则数组可由m个元素组成:
P[0],P[1],…,P[m-1]
它们的初值为P[0]∶=0,P[1]∶=1,…,P[m-1]∶= m-1
用一指针k指示当要装入新页时应调出的页在数组的位置,k的初值为“0”。
j∶= P[k]
|
j页的修改标志=1? |
输出“OUTj” |
P[k]∶=L k∶=(k+1) mod m |
修改页表 |
输出“IN L” |
取一条指令 |
开始 |
页标志=1? |
输出绝对地址 |
取一条指令 |
输出“﹡页号” |
取指令中访问的页号=>L |
查页表 |
形成绝对地址 |
置L页修改标志”1” |
结束 |
是”存”指令? |
有后继指令? |
否(产生缺页中断) |
是 |
否 |
否 |
否 |
是 |
是 |
模拟硬件 地址转换 |
模拟FIFO页面调度 |
是 |
图3-1 地址转换和FIFO页面调度流程
当产生缺页中断后,操作系统总是选择P[k]所指出的页面调出,然后执行
P[k]∶=要装入的新页页号
k∶=(k+1)mod m
在实验中不必实际地启动磁盘执行调出一页和装入一页的工作,而用输出“OUT调出的页号”和“IN要装入的新页页号”来模拟一次调出和装入的过程。模拟程序的流程见图3-1。
- 假定主存的每块长度为1024个字节,现有一个共7页的作业,其副本已在磁盘上。系统为该作业分配了4块主存块,且该作业的第0页至第3页已经装入主存,其余3页尚未装入主存,该作业的页表见表3-2所示。
表3-2 作业的页表
页号 | 标志 | 主存块号 | 修改标志 | 在磁盘上的位置 |
0 | 1 | 5 | 0 | 011 |
1 | 1 | 8 | 0 | 012 |
2 | 1 | 9 | 0 | 013 |
3 | 1 | 1 | 0 | 021 |
4 | 0 |
| 0 | 022 |
5 | 0 |
| 0 | 023 |
6 | 0 |
| 0 | 121 |
如果该作业依次执行的指令序列如表3-3所示。
表3-3 作业依次执行的指令序列
操作 | 页号 | 页内地址 | 操作 | 页号 | 页内地址 |
+ | 0 | 070 | 移位 | 4 | 053 |
+ | 1 | 050 | + | 5 | 023 |
× | 2 | 015 | 存 | 1 | 037 |
存 | 3 | 021 | 取 | 2 | 078 |
取 | 0 | 056 | + | 4 | 001 |
- | 6 | 040 | 存 | 6 | 084 |
依次执行上述的指令序列来调试你所设计的程序(仅模拟指令的执行,不必考虑指令序列中具体操作的执行)
- 为了检查程序的正确性,可自行确定若干组指令序列,运行设计的程序,核对执行结果。
- 实验代码:
#include<iostream>
#include <cstring>
#include<string>
#define NUM 7
#define WNUM 12
using namespace std;
struct pagetable
{
int num;// 页号
int flag;// 标志
int block;// 主存块号
int modify;// 修改标志
int location;// 磁盘上的位置
};
// 主存块号是-1 说明该页没有调入主存
struct pagetable
page[NUM]={{0,1,5,0,010},{1,1,8,0,012},{2,1,9,0,013},{3,1,1,0,021},{4,0,-1,0,022},{5,0,
-1,0,023},{6,0,-1,0,121}};
struct work
{
char operation[10];// 操作
int pagenum;// 页号
int address;// 页内地址
};
struct work w[WNUM]={{"+",0,70},{"+",1,50},{"*",2,15},{" 存",3,21},
{" 取",0,56},{"-",6,40},{" 移位",4,53},{"+",5,23},
{" 存",1,37},{" 取",2,78},{"+",4,1},{" 存",6,84}};
int main()
{
int k=0;// 当要装入新页时应调出的页在数组的位置
int m=4;// 允许分配的最大块数
int curpage = 0;// 当前页号
int p[4] = {0,1,2,3};// 当前已在主存中的页面
int replace;// 替换页的页号
int tempflag;
int tempmodify;
long memoryaddress;// 物理地址(绝对地址)
cout<<" 最后的结果是:"<<endl;
printf("n 操作t页号t页内地址 标志 绝对地址 修改页号 绝对地址 修改标志n");
for(int i=0;i<WNUM;i++)
{
curpage = w[i].pagenum;
tempflag = page[curpage].flag;
if(page[curpage].flag == 0)
{
replace = p[k];
p[k] = curpage;
k=(k+1)%m;
page[curpage].flag = 1;
page[curpage].block = page[replace].block;
tempmodify = page[replace].modify;
page[replace].block = -1;
page[replace].flag = 0;
page[replace].modify = 0;
}
memoryaddress = 1024*page[curpage].block+w[i].address;
if(!strcmp(w[i].operation," 存") || !strcmp(w[i].operation," 写"))
page[curpage].modify=1;
else
page[curpage].modify=0;
printf(" %st",w[i].operation);
printf(" %dt",w[i].pagenum);
printf(" %dt",w[i].address);
printf(" %dt",tempflag);
if(tempflag==1)
printf(" %dt",memoryaddress);
else
printf(" *%dt",w[i].pagenum);
if(tempflag==1)
printf(" t");
else
printf(" %d->%dt",w[i].pagenum,replace);
printf(" %dt",memoryaddress);
printf(" %dt",page[curpage].modify);
printf("n");
}
}
四、实验结果:
实验结果截图如下:
输入为:表3-3 作业依次执行的指令序列
操作 | 页号 | 页内地址 | 操作 | 页号 | 页内地址 |
+ | 0 | 070 | 移位 | 4 | 053 |
+ | 1 | 050 | + | 5 | 023 |
× | 2 | 015 | 存 | 1 | 037 |
存 | 3 | 021 | 取 | 2 | 078 |
取 | 0 | 056 | + | 4 | 001 |
- | 6 | 040 | 存 | 6 | 084 |
五、心得体会:
C++编程可以模拟实现很多操作系统原理,通过一步步实现其中的原理,可以帮助更好地深入理解操作系统内部构造,将抽象的东西具体化。在实际运行过程,把有关作业的全部信息都装入主存储器后,作业执行时实际上不是同时使用全部信息的,有些部分运行一遍便再也不用,甚至有些部分在作业执行的整个过程中都不会被使用到(如错误处理部分)。进程在运行时不用的,或暂时不用的,或某种条件下才用的程序和数据,全部驻留于内存中是对宝贵的主存资源的一种浪费,大大降低了主存利用率。
于是,提出了这样的问题:作业提交时,先全部进入辅助存储器,作业投入运行时,能否不把作业的全部信息同时装入主存储器,而是将其中当前使用部分先装入主存储器,其余暂时不用的部分先存放在作为主存扩充的辅助存储器中,待用到这些信息时,再由系统自动把它们装入到主存储器中,这就是虚拟存储器的基本思路。这都是通过编程来解决操作系统中实际遇到的问题,对上课了解的知识能给予很好地扩充。
最后
以上就是无聊小蜜蜂为你收集整理的理工大计算机操作系统实验报告实验一 几种操作系统的界面实验二 进程调度程序设计实验三 存储管理程序设计的全部内容,希望文章能够帮你解决理工大计算机操作系统实验报告实验一 几种操作系统的界面实验二 进程调度程序设计实验三 存储管理程序设计所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复