实验二进程管理
(二)进程的控制实验
思考题:
1. 可执行文件加载时进行了哪些处理?
解:可执行文件加载时首先是创建一个新进程的fork系统调用,然后用于实现进程自我终止的exit系统调用;改变进程原有代码的exec系统调用;用于将调用进程挂起并等待子进程终止的wait系统调用;获得进程标识符的getpid系统调用等处理过程。
2. 什么是进程同步?wait(0)是如何实现进程同步的? 解:进程同步是指对多个相关进程在执行次序上进行协调,以使并发执行的主进程之间有效地共享资源和相互合作,从而使程序的执行具有可在现行。
首先程序在调用fork()机那里了一个子进程后,马上调用wait(),使父进程在子进程调用之前一直处于睡眠状态,这样就使子进程先运行,子进程运行exec()装入命令后,然后调用wait(0),使子进程和父进程并发执行,实现进程同步。
实验三进程间的通信
(一) 信号机制实验
一.参考程序
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
Void waiting(),stop();
Intwait_mark;
Main()
{
Int P1,P2,stdout;
While((P1=fork())==-1); /*创建子进程P1*/
If(P1>0)
{
While((p2=fork())==-1); /*创建子进程P2*/ If(P2>0)
{
Wait_mark=1;
Signal(SIGINT,stop); /*接收到^C信号,转stop*/ Waiting();
Kill(P1,16); /*向P1发软中断信号16*/
Kill(P2,17); /*向P2发软中断信号17*/
Wait(0); /*同步*/
Wait(0);
Printf(“Parent process is killed!\n”);
Exit(0);
}
Else
{
Wait_mark=1;
Signal(17,stop); /*接收到软中断信号17,转stop*/ Waiting();
Lockf(stdout,1,0);
Printf(“Child process 2 is killed by parent!\n); Lockf(stdout,0,0);
Exit(0);
}
}
Else
{
Wait_mark=1;
Signal(16,stop); /*接收到软中断信号16,转stop*/ Waiting();
Lockf(stdout,1,0);
Printf(“Child process 1 is killed by parent!\n”); Lockf(stdout,0,0);
Exit(0);
}
}
Void waiting()
{
While(wait_mark!=0);
}
Void stop()
{
Wait_mark=0;
}
二.思考:
1. 该程序段前面部分用了两个wait(0),他们起什么作用?
解:用了两个wait(0)的作用是同时使两个子进程P1和P2发出软中断信号,而不用等待。
2. 该程序段中每个进程退出时都用了语句exit(0),为什么?
解:用exit(0)的作用是使子进程实现自我终止,正常退出此次操作,返回操作系统。
3. 为何预期的结果并未显示出来?
解:因为只执行成功两个子进程,但是并没有调用两个子进程P1,P2。当signal()让父进程捕捉从键盘上来的信号(按下^C或者break键时),只有捕捉到信号后,父进程用系统调用kill()向两个子进程发出信号。当子进程捕捉到信号后才能输出信息,之后父进程输出信息。
4. 程序该如何修改才能得到正确结果?
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
Void waiting(),stop(),alarming();
Intwait_mark;
Main()
{
Int P1,P2,stdout;
if (P1=fork()); /*创建子进程P1*/
{
If (p2=fork()); /*创建子进程P2*/
{
Wait_mark=1;
Signal(SIGINT,stop); /*接收到^C信号,转stop*/
Signal(SIGALRM,alarming);/*接收SIGALRM*/
Waiting();
Kill(P1,16); /*向P1发软中断信号16*/
Kill(P2,17); /*向P2发软中断信号17*/
Wait(0); /*同步*/
Wait(0);
Printf(“Parent process is killed!\n”);
Exit(0);
}
Else
{
Wait_mark=1;
Signal(17,stop); /*接收到软中断信号17,转stop*/
Signal(17,stop);
Signal(SIGINT,SIG_IGN);/*忽略^C信号*/
While(wait_mark!=0);
Lockf(stdout,1,0);
Printf(“Child process 2 is killed by parent!\n);
Lockf(stdout,0,0);
Exit(0);
}
}
Else
{
Wait_mark=1;
Signal(16,stop); /*接收到软中断信号16,转stop*/
Signal(SIGINT,SIG_IGN);
While(wait_mark!=0)
Lockf(stdout,1,0);
Printf(“Child process 1 is killed by parent!\n”);
Lockf(stdout,0,0);
Exit(0);
}
}
Void waiting()
{
Sleep(5);
if(wait_mark!=0);
kill(getpid(),SIGALRM);
}
Void alarming()
{
Wait_mark=0;
}
Void stop();
{
Wait_mark=0
}
5. 不修改程序如何得到期望的输出?
解:不做任何操作等待五秒钟父进程会在子进程先退出后退出,并打印退出顺序。
(二) 进程的管道通信实验
思考题:
1. 程序中的sleep(5)起什么作用?
解:sleep(5)是使管道自我阻塞5秒,这样做的目的是令读进程把管道中的已有数据读完后,暂时进入睡眠状态等待,直至写进程又将数据写入管道后,再将读进程唤醒。
2. 子进程1和子进程2为什么也能对管道进行操作? 解:因为他们的读指针和写指针都指向了管道的索引节点。
实验四存储管理
常用页面置换算法模拟实验
思考题:
1.从分析算法的命中率看,OPT最高,其次是NUR相对较高,而FIFO与LRU相差无几,最低的是LFU?
从上述结果可知,在内页面数较少(4~5)时,五种算法的命中率差别不大,都是30%左右,在内页面为7~18个页面之间,五种算法的访内命中率大致在35%~60%之间变化。但是,FIFO算法与OPT算法直接爱你的差别一般在6~10个百分点左右。在内页面为25~32个页面时,由于用户进程的所有指令基本都已装入内存,是命中率增加。因而OPT算法运行有可能出现错误。
这个免费,文库上那个家伙要10分,下着蛋疼
实验 进程状态转换及其PCB的变化
一、程序流程图:
二、使用的数据结构及说明:
在本实验中,主要用到的数据结构是PCB的结构,其中PCB的数据结构如下:
struct PCB
{
int P_Id; //PCB的ID号
char P_Name[10]; //PCB的名称
char P_State[10]; //PCB状态
int P_Runtime; //PCB的所需要的运行时间
int P_Requiry; //PCB所需要的资源要求
struct PCB * next ; //PCB块的下一个指针
} ;
其中,P_Id,和P_Name用来标示一个进程,而P_State用来标示进程的五种状态:Create_state,Ready_state,Block_state,Run_state,Exit_state。P_Runtime标示要完成一个进程所需要的时间。P_Requiry标示一个进程的执行所需要的其他条件,当其他的条件满足,则P_Requiry置1,否则置0。Struct PCB * next 用来指向同一队列中的下一个PCB块。
三、程序源代码:
#include"stdlib.h"
#include"stdio.h"
#include"string.h"
/********** globle structure and viable ******/
struct PCB
{
int P_Id; //PCB的ID号
char P_Name[10]; //PCB的名称
char P_State[10]; //PCB状态
int P_Runtime; //PCB的所需要的运行时间
int P_Requiry; //PCB所需要的资源要求
struct PCB * next ; //PCB块的下一个指针
} ;
struct PCB * Create_state; //创建状态
struct PCB * Run_state; //运行状态
struct PCB * Ready_state; //就绪状态
struct PCB * Block_state; //阻塞状态
struct PCB * Exit_state; //退出状态
int signal4=0; //标示进程4的完成状态
int signal5=0; //标示进程5的完成状态
void InsertQueue(struct PCB **head,struct PCB *node) /* insert node function */
{
struct PCB * p,*q;
node->next=NULL;
if(*head==NULL) //如果队列为空
{
*head=node;
}
Else //队列不空
{
p=*head;
q=p->next;
while(q!=NULL) //找到最后的元素位置
{
p=q;
q=q->next;
}
p->next=node; //将节点插入队列
}
}
void DeleteQueue(struct PCB **head,struct PCB *node) //撤销进程,从队列中删除元素
{
struct PCB *p,*q;
q=*head;
if(*head==NULL||node==NULL) //如果队列为空,返回
return ;
if(*head==node) //如果要删除的元素是队首元素
{
*head=(*head)->next;
return;
}
Else //如果不是队列的首元素
{
while(q->next!=p&&q->next!=NULL)
q=q->next;
q=p->next;
p->next=NULL;
}
}
void Display_Process(struct PCB * node) //打印进程状态的元素函数
{
printf("\n\nthis process Id is : %d \n",node->P_Id);
printf("this process name is : %s \n",node->P_Name);
printf("this process state is : on %s \n ",node->P_State);
printf("this process Runtime is : %d \n",node->P_Runtime);
if(node->P_Requiry)
printf("this process resource is ready \n");
else
printf("this process resource is not ready ! \n");
}
void DispatchToBlock(struct PCB *node) // /* dispatch to block function*/
{ //调度到阻塞状态的函数
//struct PCB *p=(struct PCB *)malloc(sizeof(struct PCB));
if(!node->P_Requiry) //如果所需要的资源没有满足则,调度到阻塞状态
{
strcpy(node->P_State,"block");
InsertQueue(&Block_state,node); //插入到阻塞队列
Display_Process(node);
}
}
void DispatchToReady(struct PCB *node) // dispatch to ready state
{ //调度到就绪状态的函数
if(node->P_Requiry) //如果所需的资源满足,则调度
{
strcpy(node->P_State,"Ready");
InsertQueue(&Ready_state,node);
Display_Process(node);
}
}
void DispatchBlockToReady() //dispatch the process to readyqueue
{ //从阻塞状态调度到就绪状态函数
struct PCB*p,*q;
q=Block_state;
while(q!=NULL) //如果阻塞状态队列不空
{
p=q;
q=q->next;
if(signal4&&p->P_Id==4) //如果所需要的资源满足
{
DeleteQueue(&Block_state,p);
strcpy(p->P_State,"ready");
InsertQueue(&Ready_state,p);
printf("process4 will be in the state of ready!\n");
Display_Process(p);
}
if(signal5&&p->P_Id==5)
{
DeleteQueue(&Block_state,p);
strcpy(p->P_State,"ready");
InsertQueue(&Ready_state,p);
printf("process5 will be in the state of ready!\n");
Display_Process(p);
}
}
}
void Create_Process() //创建进程函数
{
int i;
struct PCB *p;
char name[10];
strcpy(name,"process");
for(i=1;i<3;i++) //动态创建2个处于阻塞状态的进程
{
p=(struct PCB *)malloc(sizeof(struct PCB));
p->P_Id=i;
name[7]=i+'0';
name[8]='\0';
strcpy(p->P_Name,name);
strcpy(p->P_State,"create");
p->P_Runtime=1; //所需要的时间片为1
p->P_Requiry=0;
Display_Process(p);
sleep(4);
printf(" \n process%d will be in the state of Block, waiting the resource ready \n\n",i);
DispatchToBlock(p); //同时调度到阻塞队列
}
for(i=3;i<7;i++) //创建4个就绪状态的队列
{
p=(struct PCB *)malloc(sizeof(struct PCB));
p->P_Id=i;
name[7]=i+'0';
name[8]='\0';
strcpy(p->P_Name,name);
strcpy(p->P_State,"create");
p->P_Requiry=1;
if(i==6) //在这里个进程6所需要的时间片为2
p->P_Runtime=2;
else
p->P_Runtime=1;
Display_Process(p);
sleep(4);
printf(" \n process%d will be in the state of Ready, waiting to run \n\n",i);
DispatchToReady(p);
}
}
void display(struct PCB **head) //打印各个状态队列里进程数目
{
struct PCB *p,*q;
p=*head;
while(p!=NULL)
{
sleep(2);
//printf("\n\n///////////////////////////////////\n");
printf("\n\nthis process Id is : %d \n",p->P_Id);
printf("this process name is : %s \n",p->P_Name);
printf("this process state is : on %s \n ",p->P_State);
printf("this process Runtime is : %d \n",p->P_Runtime);
if(p->P_Requiry)
printf("this process resource is ready \n");
else
printf("this process resource is not ready ! \n");
p=p->next;
}
}
void Process_Run() //进程运行函数
{
struct PCB *p,*q;
p=Ready_state;
q=p;
while(p!=NULL) //就绪队列不空则继续执行
{
if(p->P_Runtime<=0) break; //如果时间片执行完了,则跳出循环
strcpy(p->P_State,"running");
Display_Process(p);
p->P_Runtime=p->P_Runtime-1;
sleep(4);
if(p->P_Runtime>0) //没有完成,则进入就绪队列
{
printf("this process is not finished,will be dispatch to the ready queue!!\n");
DeleteQueue(&Ready_state,p);
strcpy(p->P_State,"ready");
InsertQueue(&Ready_state,p);
Display_Process(p);
}
Else //执行完成,则跳出,并发送相应的信息
{
printf("\n\nProcess%d is finished and will be in the state of exit!\n\n",p->P_Id);
if(p->P_Id==4) signal4=1;
if(p->P_Id==5) signal5=1;
}
if(signal4||signal5)
DispatchBlockToReady(); //如果资源满足,则将进程调度到就绪队列
q=q->next;
p=q;
}
if(q==NULL)
printf("\nthere is no process ready!\n STOP Machine!!!\n");
}
int main(int argc,char * argv[]) //主函数
{
int i;
char c='c'; //界面
printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \n");
printf("...................................Ding Hai bo\n");
printf("......Press s to start the process.......\n");
scanf("%c",&c);
while(1)
{
if(c=='s')break;
scanf("%c",&c);
}
Create_Process(); //调用创建进程函数
printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
printf("\n>>>>>>> Display the Ready queue >>>>>>>>>>>>>>>\n");
sleep(5);
display(&Ready_state); ////////////////显示就绪队列里的进程
printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
printf("\n>>>>>>>> Display the Block queue >>>>>>>>>>>>\n");
sleep(5); //显示阻塞队列函数
display(&Block_state); /////////////////////
printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n\n");
printf("\n>>>>>>>> Now the process start to run >>>>>>>>>>>\n");
sleep(5);
Process_Run(); //调用进程运行函数
}
四、运行结果及说明:
运行结果的截图:
下面的运行结果是程序执行的每一步进程调度的显示,从进程的创建到进程的执行,结束,每一步进程调度都有显示。
五.程序使用说明:
1)输入字符’s’启动程序
2)程序将自动执行,自动创建进程,运行进程和结束进程。
3)程序将自动显示每一步进程的执行状态。
《计算机操作系统》实验报告班级:姓名:学号:实验一进程控制与描述一、实验目的通过对Windows2000编程,进一步熟悉操作系统的…
操作系统实验报告实验名称理解UNIXLINUXShell及UNIX的进程树成绩专业班级计科姓名学号联系电话实验日期20xx年12月…
目录实验一进程的创建2实验二进程控制3实验三进程的管道通信4实验四消息通信6实验五进程调度算法8实验六FIFO页面置换算法12实验…
操作系统实验报告学号姓名班级实验一实验报告实验名称并发程序设计实验1实验目的掌握在程序中创建新进程的方法观察并理解多道程序并发执行…
《操作系统原理》实验报告院(部):管理工程学院专业:信息管理与信息系统实验项目:实验一二三五班级:信管102姓名:学号:目录引言.…
沈阳理工大学课程设计任务书1沈阳理工大学目录1课程设计目的32课程设计要求33相关知识34需求分析45概要设计56详细设计67测试…
实验二进程管理一进程的创建实验思考题1系统是怎样创建进程的解linux系统创建进程都是用fork系统调用创建子进程2当首次调用新创…
XXXX大学20xx年20xx年第2学期院系计算机信息工程学院专业信息管理与信息系统课程名称操作系统原理及应用班级姓名学号指导教师…
实验一进程管理一目的进程调度是处理机管理的核心内容本实验要求编写和调试一个简单的进程调度程序通过本实验加深理解有关进程控制块进程队…
一、实验目的本实验要求学生编写和调试一个系统动态分配资源的简单模拟程序,观察死锁产生的条件,并采用适当的算法,有效地防止和避免死锁…
操作系统实验报告实验1分析实验结果参照实验指导书回答下面的问题56从实验中得到了两次不同的结果原因是程序采用了多线程的写法两个线程…