操作系统实验报告
安徽师范大学 计算机与信息学院
姓名: XXX 学号: 1911130XXXX 年级专业: 软工二班
实 验 题 目: 实现进程状态转化
【1.需求分析】
利用高级语言编写程序,模拟进程状态转换的过程。
进程的主要状态:就绪、运行、阻塞、终止,状态之间的转换如下图所示:
(1)输入形式:进程名、运行的时间片数、初始优先级且随时添加新进程。
(2)输出形式:实时输出进程转换的信息。
(3)程序功能:模拟进程状态转换过程。
【2.概要设计】
设计思路:采用可视化的集成开发环境 Visual Studio 2019。编程语言采用 C#。在实验一搭建的交互式实验系统框架的基础上,通过对其中的“进程状态转换”子窗口的编辑完善。
采用进程控制块(PCB)描述一个进程的所有信息包括:进程标识符、处理机状态、进程调度信息以及控制信息,它是系统感知进程存在的唯一标志,进程与 PCB是一一对应的。
对PCB 中的内容在此可做一些简化处理,只包括:进程标识符(内部标识符、外部标识符)、当前状态(“就绪”,“阻塞”,“执行”和“终止”)、要求运行的时间片数、优先级等。
模拟过程
按优先级高低对进程进行调度,每个进程可有四个状态,即:“就绪”,“阻塞”,“执行”和“消亡”(假设优先数越大优先级越高,以及进程的初始状态为就绪状态)。
为便于处理,应该随机地赋予所有进程各自的“优先级”和“要求运行的时间片数”,由用户给定。
程序中共设 4 个队列:就绪队列、执行队列、阻塞队列和消亡队列。
按优先级调度时,进程每运行一次,优先级降低一位,要求的时间片数减 1,如果要求的时间片数为零了,则将其加入终止队列。否则,将其按照优先级的次序重新加入就绪队列。
要求的时间片数为零了,则将其加入终止队列。否则,将其按照优先级的次序重新加入就绪队列。
进程运行过程中,遇到阻塞时,将该进程加入阻塞队列。(通过随机函数得到随机数,满足某种情况则使之加入到阻塞队列,或人为设置是否阻塞)。
重复调度,直到就绪队列中所有进程全部运行结束。
流程图:
【3.详细设计】
定义的类类型PCB的实现如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text;
namespace 操作系统实验一
{
class PCB
{
public int Pid //内部标识符
{
get;
set;
}
public string Processname //外部标识符(进程名称)
{
get;
set;
}
public int Timeslice //要求运行的时间片数
{
get;
set;
}
public int Priority //优先级
{
get;
set;
}
public string State //状态
{
get;
set;
}
}
}
本次实验的主要操作代码如下:
随机创建:
自定义创建:
运行操作:
阻塞操作:
唤醒操作:
模拟CPU运行函数timer1_Tick函数
【4.测试结果】
随机创建几个进程:
自定义创建:
运行:
阻塞:
唤醒:
相关设置:
可以更换背景颜色
暂停程序运行(暂停时不能进行其他操作)
【5.源代码】
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 操作系统实验一
{
public partial class Form2 : Form
{
public int pid = 0; //进程ID
public string Processname; //进程名
public int Timeslice; //时间片
public int Priority; //优先级
public int flag = 0;//标志
public int i = 0;
public int time1 = 0;
List<PCB> ready = new List<PCB>(); //就绪队列
List<PCB> running = new List<PCB>(); //运行队列
List<PCB> clog = new List<PCB>(); //阻塞队列
List<PCB> destroy = new List<PCB>(); //消亡队列
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
if (ready.Count + running.Count + clog.Count + destroy.Count >= 100) { MessageBox.Show("最多创建100个进程!", "错误"); }
else
{
PCB pcb = new PCB();
pcb.Pid = ++pid;
pcb.Processname = this.textBox2.Text;
pcb.Priority = Convert.ToInt32(this.textBox3.Text);
pcb.Timeslice = Convert.ToInt32(this.textBox4.Text);
pcb.State = "就绪";
ready.Add(pcb);
ready.Sort(delegate (PCB x, PCB y) //排序
{
return y.Priority.CompareTo(x.Priority);
});
string str = "进程" + pcb.Pid + "创建成功!\n";
richTextBox1.AppendText(str);
this.dataGridView1.DataSource = new BindingList<PCB>(ready);
this.textBox2.Text = "";//输入框置空
this.textBox3.Text = "";//输入框置空
this.textBox4.Text = "";//输入框置空
}
}
private void button2_Click(object sender, EventArgs e)
{
if (ready.Count + running.Count + clog.Count + destroy.Count >= 100) { MessageBox.Show("最多创建100个进程!", "错误"); }
else
{
PCB pcb = new PCB();
pcb.Pid = ++pid;
Random RA = new Random(); //生成随机数
pcb.Processname = this.textBox1.Text;
pcb.Timeslice = RA.Next(1, 24);
pcb.Priority = RA.Next(1, 24)+ pcb.Timeslice;
pcb.State = "就绪";
ready.Add(pcb);
ready.Sort(delegate (PCB x, PCB y) //排序
{
return y.Priority.CompareTo(x.Priority);
});
string str = "进程" + pcb.Pid + "创建成功!\n";
richTextBox1.AppendText(str);
this.dataGridView1.DataSource = new BindingList<PCB>(ready);
this.textBox1.Text = "";
}
}
private void groupBox1_Enter(object sender, EventArgs e)
{
}
private void label1_Click(object sender, EventArgs e)
{
}
private void button3_Click(object sender, EventArgs e)
{
go();//调用运行函数
}
private void button4_Click(object sender, EventArgs e)
{
if (flag == 1)//暂停运行
{
MessageBox.Show("运行已暂停,请重新启动!", "错误");
}
else if (running.Count == 0)
{
MessageBox.Show("运行队列为空,无法阻塞任何进程!", "错误");
}
else //阻塞正在运行的进程
{
timer1.Stop();
running[0].State = "阻塞";
clog.Add(running[0]);
richTextBox1.AppendText("进程" + running[0].Pid + "执行--->阻塞\n");
running.RemoveAt(0);
this.dataGridView3.DataSource = new BindingList<PCB>(clog);
this.dataGridView2.DataSource = new BindingList<PCB>(running);
if (running.Count == 0 && ready.Count != 0) go();
}
}
private void button5_Click(object sender, EventArgs e)
{
if (flag == 1)//暂停运行
{
MessageBox.Show("运行已暂停,请重新启动!", "错误");
}
else if (clog.Count == 0)
{
MessageBox.Show("阻塞队列为空,无法唤醒任何进程!", "错误");
}
else if (clog.Count > 0)
{//唤醒被阻塞进程
clog[0].State = "就绪";
ready.Add(clog[0]);
richTextBox1.AppendText("进程" + clog[0].Pid + "阻塞--->就绪\n");
clog.RemoveAt(0);
ready.Sort(delegate (PCB x, PCB y)
{
return y.Priority.CompareTo(x.Priority);
});
this.dataGridView1.DataSource = new BindingList<PCB>(ready);
this.dataGridView3.DataSource = new BindingList<PCB>(clog);
if (running.Count == 0 && ready.Count != 0) go();
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (running.Count == 1 && running[0].Timeslice > 0) //运行队列为空且未运行完
{
running[0].Timeslice--;
running[0].Priority--;
this.dataGridView2.DataSource = new BindingList<PCB>(running);
time1++;
richTextBox1.AppendText(time1 + "秒过去……\n");
}
else if (running.Count == 1 && running[0].Timeslice == 0) //运行队列完成
{
running[0].State = "消亡";
destroy.Add(running[0]);
richTextBox1.AppendText("进程" + running[0].Pid + "执行--->消亡\n");
running.RemoveAt(0);
this.dataGridView4.DataSource = new BindingList<PCB>(destroy);
this.dataGridView2.DataSource = new BindingList<PCB>(running);
if (running.Count == 0 && ready.Count != 0) go(); //若运行队列为空且就绪队列还有进程,继续运行进程。
}
}
private void go() //开始
{
if(flag == 1)//暂停
{
MessageBox.Show("运行已暂停,请重新启动!", "错误");
}
else if (ready.Count == 0) //若就绪队列为空,无法执行
{
MessageBox.Show("就绪队列为空,无法执行!", "错误");
}
else //就绪队列非空
{
if (running.Count == 0)
{
ready[0].State = "执行";
running.Add(ready[0]);
ready.RemoveAt(0);
richTextBox1.AppendText("进程" + running[0].Pid + "就绪--->执行\n");
this.dataGridView2.DataSource = new BindingList<PCB>(running);
this.dataGridView1.DataSource = new BindingList<PCB>(ready);
timer1.Start();
}
}
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
richTextBox1.SelectionStart = richTextBox1.Text.Length;
richTextBox1.SelectionLength = 0;
richTextBox1.ScrollToCaret();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void dataGridView2_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void button6_Click(object sender, EventArgs e)
{
if (colorDialog1.ShowDialog() == DialogResult.OK)
{
this.BackColor = colorDialog1.Color;
}
}
private void button7_Click(object sender, EventArgs e)
{
timer1.Enabled = false;
}
private void 更换背景颜色ToolStripMenuItem_Click(object sender, EventArgs e)
{
if (colorDialog1.ShowDialog() == DialogResult.OK)
{
this.BackColor = colorDialog1.Color;
}
}
private void 暂停运行ToolStripMenuItem_Click(object sender, EventArgs e)
{
timer1.Enabled = false;
flag = 1;
}
private void 重新启动ToolStripMenuItem_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
flag = 0;
}
private void textBox3_TextChanged(object sender, EventArgs e)
{
}
}
}
PCB:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text;
namespace 操作系统实验一
{
class PCB
{
public int Pid //内部标识符
{
get;
set;
}
public string Processname //外部标识符(进程名称)
{
get;
set;
}
public int Timeslice //要求运行的时间片数
{
get;
set;
}
public int Priority //优先级
{
get;
set;
}
public string State //状态
{
get;
set;
}
}
}