- 相关推荐
操作系统实验二:进程管理
篇一:操作系统实验报告 实验一 进程管理
一、目的
进程调度是处理机管理的核心内容。本实验要求编写和调试一个简单的进程调度程序。通过本实验加深理解有关进程控制块、进程队列的概念,并体会和了解进程调度算法的具体实施办法。
二、实验内容及要求
1、设计进程控制块PCB的结构(PCB结构通常包括以下信息:进程名(进程ID)、进程优先数、轮转时间片、进程所占用的CPU时间、进程的状态、当前队列指针等。可根据实验的不同,PCB结构的内容可以作适当的增删)。为了便于处理,程序中的某进程运行时间以时间片为单位计算。各进程的轮转时间数以及进程需运行的时间片数的初始值均由用户给定。
2、系统资源(r1…rw),共有w类,每类数目为r1…rw。随 机产生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,并排列到就绪队列的尾上。
三、实验环境
操作系统环境: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;
listBox1.Items.Add("产生进程ID:" + jincheng.id);
listBox1.Items.Add("所需A资源数目:" + jincheng.ra);
listBox1.Items.Add("所需B资源数目:" + jincheng.rb);
listBox1.Items.Add("所需C资源数目:" + jincheng.rc);
listBox1.Items.Add("所需时间片数:" + jincheng.ntime);
if ((a - jincheng.ra) >= 0 && (b - jincheng.rb) >= 0 && (c - jincheng.rc) >= 0)
{
a = a - jincheng.ra;
b = b - jincheng.rb;
c = c - jincheng.rc;
jincheng.state = 'W';
hready.Add(jincheng);//加入就绪队列
}
else
{
jincheng.state = 'B';
hblock.Add(jincheng);//加入阻塞队列
}
listBox1.Items.Add("当前进程状态:" + jincheng.state);
}
}
//从数组起始地址开始输出该数组的内容
public void disp(ArrayList list)
{
ArrayList list1 = new ArrayList();
list1 = list;
if (list1.Count > 0)
{
for (int j = 0; j < list1.Count; j++)
{
pcb p = (pcb)list1[j];
listBox1.Items.Add(" " + p.id.ToString() + " " + p.state.ToString() + "
p.ra.ToString() + "" + p.rb.ToString() + "" + p.rc.ToString()+"
p.ntime.ToString() + " " + p.rtime.ToString() + " ");
}
}
else
{
listBox1.Items.Add(" 该队列中没有进程! ");
}
}
//输出就绪数组和阻塞数组的信息
public void outputall()
{
listBox1.Items.Add(" =======CPU运行了:" + h.ToString() + "次======= ");
listBox1.Items.Add("*********当前就绪队列的信息!*********");
listBox1.Items.Add("进程ID 进程状态 A资源数 B资源数 C资源数 所需时间片 已运行时间片");
disp(hready);
listBox1.Items.Add("*********当前就阻塞列的信息!*********");
listBox1.Items.Add("进程ID 进程状态 A资源数 B资源数 C资源 所需时间片 已运行时间片");
disp(hblock);
}
//运行就绪数组的头进程,运行一个时间片,轮转一个时间片,时间片轮转调度算法
public void running()
{
ArrayList hready1 = new ArrayList();
hready1 = hready;
pcb p1 = new pcb();
p1=(pcb)hready1[0];
p1.state='R';
p1.rtime= p1.rtime + 1;
h=h+1;
listBox1.Items.Add(" ~~~~~~~当前正在运行进程ID是:" +p1.id + "~~~~~~~~ ");
listBox1.Items.Add(" 进程ID 进程状态 A资源数 B资源数 C资源数 所需时间片 已运行时间片 ");
listBox1.Items.Add(p1.id + " " +p1.state+ "" + p1.ra + " " + p1.rb + "" + p1.rc + "" + p1.ntime + "" + p1.rtime);
if (p1.ntime==p1.rtime)
{
listBox1.Items.Add(p1.id.ToString()+"的进程已经完成! ");
a = a + p1.ra;
b = b + p1.rb;
c = c + p1.rc;
hready.RemoveAt(0);
}
else
{
p1.state='W';
hready1.Add(p1);
hready.RemoveAt(0);
}
}
//检测当前资源数目是否满足阻塞数组里进程的需求
public void testblock()
{
ArrayList hblock1 = new ArrayList();
hblock1 = hblock;
for (int m = 0; m < hblock1.Count; m++)
{
pcb p1 = new pcb();
篇二:操作系统进程管理实验
一、实验目的
通过编写进程管理的算法,要求学生掌握整个进程管理的各个环节,进程的数据结构描述,进程的各种状态之间的转换,以及进程的调度算法。以加深对进程的概念及进程调度算法的理解,并且提高链表的应用能力,达到提高编程能力的目的。
二、实验原理及基本技术路线图(方框原理图)
用C语言或C++语言开发。需要定义PCB的数据结构,用链表的形式管理进程,采用多级反馈队列调度的算法模拟进程的控制。要求有创建、撤销、调度、阻塞、唤醒进程等功能。
①进程的状态转换图
②数据结构定义、主要变量的说明、函数的说明及各原语的功能说明
typedef struct PCB 定义结构体PCB进程控制块;char NAME[20] 定义结构体变量,进程名;long
ID 定义进程id;int RUNTIME 定义进程运行时间;char STATE[6] 定义进程状态 有 ready 、wait 、run;
int PRIORITY定义权值。 typedef struct QNode { PCB pcb; struct QNode *next; }QueuePtr; 定义单链表,有定义指针next。typedef struct LinkQueue { int prior; QueuePtr *front; QueuePtr *rear; int PartTime; }LinkQueue;
链队列中定:优先级、结构体里的QueuePtr类型指针变量,指向该优先级的进程的头结点和尾结点,还运行的时间片。LinkQueue Readyqueue[10] 链队列的单链表。
void schedule() 声明调度函数,用来调度进程的运行;void show() 声明输出函数,用来输出的一个函数;void Create()声明创建进程的函数,用来创建进程。
yunxingshijian=1+(int)(rand()%30); 此语句是随机生成一个整数赋给运行时间RUNTIME;
youxianji=1+(int)(rand()%9); 该语句随机生成一个整数(1~9)赋给优先级; strcpy(p->pcb.NAME,name)将名字赋给PCB块;strcpy(p->pcb.STATE,"Ready")将进程状态赋给PCB块; p->pcb.PRIORITY=youxianji将优先级赋给PCB块; p->pcb.RUNTIME=yunxingshijian; 将运行时间赋给PCB块; p->pcb.ID=id 将id号赋给PCB块。
{Readyqueue[i].front->next=p->next; Readyqueue[i+1].rear->next=p; Readyqueue[i+1].rear=p;p->next=NULL; } p移到下一队列的队尾,使Readyqueue[i+1].rear指向最后一个结点。{Readyqueue[i].front->next=p->next; Readyqueue[9].rear->next=p; p->next=NULL; Readyqueue[9].rear=p; } //p->next前移,把p移到运行结束的队列Readyqueue[9].rear。
③多级反馈队列调度算法的描述
一个进程被调度,则其运行时间有p->pcb.RUNTIME=p->pcb.RUNTIME-(int )pow(2,i+1),此后如果该进程的p->pcb.RUNTIME<0或p->pcb.RUNTIME=0,此进程就结束且加入到Readyqueue[9].rear->next=p且p->next=NULL。没有结束就移加到下一队列的尾部且优先级减“1”(Readyqueue[i].front->next=p->next;Readyqueue[i+1].rear->next=p;Readyqueue[i+1].rear=p;p->next=NULL; )。然后往下执行。如此循环.iv Readyqueue[i].front->next!=NULL发生时,就往下一优先级运行。直到所有进程结束。
④程序功能结构图、流程图
<1>创建进程函数Create()
三、所用仪器、材料(设备名称、型号、规格等)。
所用仪器:计算中心201;操作系统:Microsoft Visual C++;软件平台:Microsoft Visual C++
四、实验方法、步骤
#include#include#include#include#include
typedef struct PCB //定义结构体PCB进程控制块 {
typedef struct QNode//单链表 {
PCB pcb;
typedef struct LinkQueue//链队列
{
int prior; //优先级
LinkQueue Readyqueue[10]; //链队列的单链表
int N; //N为当前进程数
void schedule();//声明调度函数
void show(); //声明输出函数
void InitQueue() //队列的初始化、给每个队列加个头结点 {
for(int i=0;i<10;i++) {
Readyqueue[i].PartTime=(int )pow(2,i+1); //每个进程的时间片
Readyqueue[i].prior=9-i;//每进程的优先级
Readyqueue[i].front=(QueuePtr*)malloc(sizeof(QueuePtr)); //为进程申请空间
QueuePtr *front; //结构体里的QueuePtr类型指针变量,指向该优先级的进程的头结点
QueuePtr *rear; //结构体里的QueuePtr类型指针变量,指向该优先级的进程的尾结点
int PartTime; //时间片
struct QNode *next;
}
QueuePtr;
char NAME[20]; //结构体变量,进程名
long ID; //进程id
int RUNTIME; //进程运行时间
char STATE[6]; //进程状态
ready wait run int PRIORITY;//权值
}PCB;
}LinkQueue;
}
}
Readyqueue[i].rear=Readyqueue[i].front;//初始化单链的头结点和尾结点指向同一位置 Readyqueue[i].front->next=NULL; //初始化时Readyqueue[i].front->next为空
//***************************创建进程**************************************************
void Create() {
InitQueue();
char name[20]; long id=201031101; //定义ID和初始化为201031101
QueuePtr *p;
int yunxingshijian,youxianji;//运行时间、优先级
printf(" 请输入要创建进程的数目:");
fflush(stdin);
scanf("%d",&m);
{
printf(" 输入进程名:"); //用户输入用户名
scanf("%s",&name);
int m;
for(int j=1;j<=m;j++) //创建用户所需进程m个
srand((int)time(0));
yunxingshijian=1+(int)(rand()%30);//随机生成一个整数赋给运行时间
printf(" 运行时间:%d",yunxingshijian);
srand((int)time(0));
for(int i=0;i<9;i++) //通过优先级寻找该进程应放置的队列
{
if(youxianji==9-i)
{
k=Readyqueue[i].front; //k为移动指针,寻找队列末尾进程
strcpy(p->pcb.NAME,name); //将名字赋给PCB块
strcpy(p->pcb.STATE,"Ready");//将进程状态赋给PCB块
p->pcb.PRIORITY=youxianji;//将优先级赋给PCB块
p->pcb.RUNTIME=yunxingshijian; //将运行时间赋给PCB块
p->pcb.ID=id; //将id号赋给PCB块
youxianji=1+(int)(rand()%9);//随机生成一个整数(1~9)赋给优先级
printf(" 优先级:%d",youxianji);
p=(QueuePtr *)malloc(sizeof(QueuePtr)); //插入就绪队列
QueuePtr *k;
篇三:操作系统实验二(进程管理)
实验题目:
(1) 进程的创建编写一段程序,使用系统调用fork( )创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示字符“a”;子进程分别显示字符“b”和字符“c”。试观察记录屏幕上的显示结果,并分析原因。
(2) 进程的控制修改已编写的程序,将每个进程输出一个字符改为每个进程输出一句话,在观察程序执行时屏幕上出现的现象,并分析原因。
(3) 编制一段程序,使其实现进程的软中断通信。要求:使用系统调用fork( )创建两个子进程,再用系统调用signal( )让父进程捕捉键盘上来的中断信号(即按Del键);当捕捉到中断信号后,父进程调用系统调用kill( )向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:Child process 1 is killed by parent!Child process 2 is killed by parent! 父进程等待两个子进程终止后,输出如下的信息后终止:Parent process is killed! 在上面的程序中增加语句signal(SIGINT, SIG_IGN)和 signal(SIGQUIT, SIG_IGN),观察执行结果,并分析原因。
(4) 进程的管道通信编制一段程序,实现进程的管道通信。使用系统调用pipe( )建立一条管道线;两个进程P1和P2分别向管道各写一句话: Child 1 is sending a message! Child 2 is sending a message! 而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。要求父进程先接收子进程P1发来的消息,然后再接收子进程P2发来的消息。
实验源程序及报告:
(1)、进程的创建
#include
int main(int argc, char *argv[])
{
int pid1,pid2; /*fork first child process*/
if ( ( pid1=fork() ) < 0 )
{
printf( "ProcessCreate Failed!");
exit(-1);
}
if ( ( pid1=fork() ) == 0 )
{
printf( "b " );
}
/*fork second child process*/
if ( ( pid2=fork() ) < 0 )
{
printf( "ProcessCreate Failed!");
exit(-1);
}
if ( ( pid2=fork() ) == 0 )
{
printf( "c " );
}
/*parent process*/
else
{
wait(NULL);
printf( "a " );
exit(0);
}
return 0;
}
(2)、进程的控制
#include
int main(int argc, char *argv[])
{int pid1,pid2;
/*fork first child process*/
if ( ( pid1=fork() ) < 0 )
{
printf( "ProcessCreate Failed!");
exit(-1);
}
if ( ( pid1=fork() ) == 0 )
{
printf( "This is my Unix OS program! " );
}
/*fork second child process*/
if ( ( pid2=fork() ) < 0 )
{
printf( "ProcessCreate Failed!");
exit(-1);
}
if ( ( pid2=fork() ) == 0 )
{
printf( "This is the second Child process! " );
}
/*parent process*/
else
{
wait(NULL);
printf( "This is the Parent process " );
exit(0);
}
return 0;
}
(3) 编制一段程序,使其实现进程的软中断通信。
#include
#include
#include
#include
int wait_flag; void stop( );
main( )
{
int pid1, pid2;signal(3, stop);
while ((pid1 = fork( )) == -1);
if ( (pid1 = fork() ) > 0)
{
while ((pid2 = fork( )) == -1);
if (( pid2 = fork()) > 0 )
{
}
else
{
} wait_flag = 1;
signal(SIGINT, stop);
sleep(5);
kill(pid1, 16);
kill(pid2,17);
wait(0); wait(0);
printf(" Parent process is killed. ");
exit(0); wait_flag = 1;
signal(17, stop);
printf(" Child process 2 is killed by parent. ");
exit(0);
}
【 操作系统实验二:进程管理】相关文章:
WINDOWS操作系统的进程描述04-02
Linux进程管理优秀教程11-22
Windows操作系统的管理的详细解析03-31
操作系统实验心得体会(精选10篇)06-08
操作系统实验心得体会(通用12篇)11-28
Linux操作系统学习笔记权限管理03-19
操作系统的种类07-07
LINUX操作系统01-22
系统进程是什么03-28