实验一 进程管理
一、目的进程调度是处理机管理的核心内容。本实验要求编写和调试一个简单的进 程调度程序。
通过本实验加深理解有关进程控制块、 进程队列的概念, 并体会 和了解进程调度算法的具体实施办法。
二、实验内容及要求
1、 设计进程控制块PCB的结构(PCB吉构通常包括以下信息:进程名(进 程ID)、进程优先数、轮转时间片、进程所占用的 CPIM间、进程的状态、当 前队列指针等。可根据实验的不同,PCB结构的内容可以作适当的增删)。为 了便于处理, 程序中的某进程运行时间以时间片为单位计算。
各进程的轮转时 间数以及进程需运行的时间片数的初始值均由用户给定。
2、 系统资源(ri…rW),共有w类,每类数目为ri…s 随 机产生n进程 Pi(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 ,并排列到就绪队列的尾上。
三、实验环境
操作系统环境:Win dows系统。
编程语言: 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 = ;
n = ;
c = ;
a1 = a;
b1 = b;
c1 = c;
r = m - n;
time1Inteval = ;
= time1Inteval;
for (i = 1; i <= n; i++)
{
pcb jincheng = new pcb();
= i;
= (a) + 1);
= (b) + 1);
= (c) + 1);
= (1, 5));
= 0;
" 产生进程 ID :" + ;
" 所需A资源数目:"+;
" 所需 B 资源数目: " + ;
" 所需 C 资源数目: " + ;
" 所需时间片数: " + ;
if ((a - >= 0 && (b - >= 0 && (c - >= 0)
{
a = a - ;
b = b - ;
c = c - ;
= 'W';
(jincheng);// 加入就绪队列
}
else
{
{
= 'B';
(jincheng);// 加入阻塞队列
}
" 当前进程状态: " + ;
}
}
// 从数组起始地址开始输出该数组的内容
public void disp(ArrayList list)
{
ArrayList list1 = new ArrayList();
list1 = list;
if > 0)
{
for (int j = 0; j < ; j++)
+
+ I!
pcb p = (pcb)list1[j];I!I!I!I!I!I!I!
pcb p = (pcb)list1[j];
I!
I!
I!
I!
I!
I!
I!
I!
\r\n");
else
{
"\r\n\t 该队列中没有进程! \r\n");
}
}
// 输出就绪数组和阻塞数组的信息
public void outputall()
"\r\n=======CPU 运行了: " + () + " 次 =======\r\n");
H*********当前就绪队列的信息!
H*********
当前就绪队列的信息! *********");
I!进程 ID 进程状态 A 资源数 B 资源数 C 资源数 所需时间片 已运行时
I!
间片");
disp(hready);
H*********
当前就阻塞列的信息! *********");
" 进程 ID 进程状态 A 资源数 B 资源数 C 资源 所需时间片 已运行时间 片");
disp(hblock);
// 运行就绪数组的头进程,运行一个时间片,轮转一个时间片,时间片轮转 调度算法
public void running()
{
ArrayList hready1 = new ArrayList();
hready1 = hready;
pcb p1 = new pcb();
p1=(pcb)hready1[0];
='R';
(0);
(0);
= + 1;
h=h+1;
"\r\n~~~~~~~ 当前正在运行进程 ID 是 :" + + "~~~~~~~~\r\n");
"\r\n 进程 ID 进程状态 A 资源数 B 资源数 C 资源数 所需时间片 已 运行时间片 \r\n");
+ "
" ++ " " + + " " + + "
" +
+ "
" + + " " + ;
5
if ==
{
I!
的进程已经完成! \r\n");
a = a + ;
b = b + ;
c = c + ;
}
else
='W';
(p1);
(0);
}
}
// 检测当前资源数目是否满足阻塞数组里进程的需求
public void testblock()
{
ArrayList hblock1 = new ArrayList();
hblock1 = hblock;
for (int m = 0; m < ; m++)
{
pcb p1 = new pcb();
p1 = (pcb)hblock1[m];
if ((a - >= 0) && (b - >= 0) && (c - >= 0))
='W';
(p1);
a = a - ;
b = b - ;
c = c - ;
~~\r\n");"ID 号为: "+ + " 的进程由阻塞队列转入就绪队列
~~\r\n");
(m);
m--;
}
}
}
// 检测是否有新的进程产生,随机产生新进程
public void testnew()
int t;
if (r>0)//r
if (r>0)//r 为随机产生的进程数目
{
t = (9) + 1;
if (t <= 7)
{
"\r\n 有新的进程申请加入: ~~");
pcb jincheng = new pcb();
= i++;
= (a) + 1);
= (b) + 1);
= (c) + 1);
= (1, 5));
= 0;
" 产生进程 ID: " + ;
" 所需A资源数目:"+;
" 所需B资源数目:"+;
I!
I! 所需C资源数目:"+;
(jincheng);//
(jincheng);// 加入阻塞队列
" 所需时间片数: " + ;
if ((a - >= 0 && (b - >= 0 && (c - >= 0)
{
a = a - ;
b = b - ;
c = c - ;
= 'W';
" 进程状态为: " + ;
(jincheng);// 加入就绪队列
~~\r\n");" 资源满足新进程请求,该进程进入就绪队列
~~\r\n");
}
else
{
= 'B';
I!
I! 进程状态为: " + ;
~~\r\n");" 资源不满足新进程请求,该进程进入阻塞队列
~~\r\n");
}
}
}
r = r - 1;
}
// 系统三类资源变化情况的显示
public void rescore()// 系统三类资源变化情况的显示
{
if (a > a1) { = (); }
if (a < 0) { = "0"; }
if (a >= 0 && a < a1) { = (); }
if (b > b1) { = (); }
if (b < 0) { = "0"; }
if (b >= 0 && b <= b1) { = (); }
if (c > c1) { = (); }
if (c < 0) { = "0"; }
if (c >= 0 && c <= c1) { = (); }
}
FCFS算 法)//
FCFS算 法)
public void runFcfs()
{
if >0)
{
outputall();
running();
testblock();
testnew();
rescore();
}
else
{
{
{
{
= false;
= ();
= ();
= ();
>>>>>>>~\r\n");"\r\n<<<<<<<< 所有进程都已经运行结束!
>>>>>>>~\r\n");
}
// 计时器触发时间片轮转调度算法
private void timer1_Tick(object sender, EventArgs e)
{
runFcfs();
}
// 开始模拟按钮单击执行函数
private void button1_Click(object sender, EventArgs e)
runmain();
= false;
= false;
= false;
= false;
= false;
= false;
= false;
= false;
= false;
= false;
}
// 清除屏幕按钮单击执行函数
private void button2_Click(object sender, EventArgs e)
}
}
= true;
= true;
= true;
= true;
= true;
= true;
= true;
//运行的主函数 public void runmain()
{
input();
=true
3、运行界面和运行结果
界面中,可以任意设定需要模拟的进程总数(如5),初始化进程个数(如
3),还有A、B、C三类资源的总数(如10、10、10)。为了方便显示,还可以 设定时间片的长度(如 500 毫秒)。除此之外,在运行过程中,所有的资源都 是随机生成的, 并且其中新进程的产生也是随机的, 但是产生的进程总数不会 多于开始设定的模拟的进程总数, 以防止不断产生新进程, 程序不断运行。
在 显示窗口的上方, 还会实时显示资源的变化情况, 方便对运行的观察。
当运行 结束后,可以通过工具栏中的显示选项中的保存结果按钮,将结果保存成 txt 文件格式,方便运行后的结果分析。
五、心得体会
本次实验,我的任务是设计一个允许 n 个进程并发运行的进程管理模拟系 统。该系统包括有简单的进程控制、 同步与通讯机构, 系统在运行过程中能显 示各进程的状态及有关参数的变化情况, 从而观察诸进程的运行过程及系统的 管理过程,我是用 C#写的,在我的电脑能够运行通过,虽不能尽善尽美,但 也基本能实现老师的要求。
两个星期的实验,虽然时间有点短,但我也收获不少,这次实验,加深了 我对进程概念及进程管理的理解; 比较熟悉进程管理中主要数据结构的设计及 进程调度算法、 进程控制机构、 同步机构及通讯机构的实施。
也让我认识到自 己的不足,操作系统的有些知识,我知道的还不多,没有掌握好,还需要多多 学学,不断提升自己的能力。
实验中,我们小组分工合作,共同学习,虽然在实验中遇到了一些问题, 但在老师和同学的细心指导和热心帮助下解决了。
同时,了解到团队精神的重 要性,也为以后的学习和工作打下了坚实的基础,同时积累了宝贵的经验。