实验四:同步机构实验报告学 院: 专业班级: 姓 名: 学 号:一、实验内容:模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误二、实验目的:进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行我们把若干个进程都能进行访问和修改的那些变量称为公共变量由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问一般说,同步机构是由若干条原语——同步原语——所组成本实验要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用三、实验题目:模拟PV操作同步机构,且用PV操作解决生产者——消费者问题四、此次用到的数据结构知识如下: typedef struct Pcb{ char name[10]; //进程名 char state[10]; //运行状态 char reason[10]; //若阻塞,其原因 int breakp; //断点保护 struct Pcb *next; //阻塞时的顺序进程名状态等待原因断点后继进程 }Pcb,*link; 进程控制块结构 定义两个进程: link p1;//生产者进程,link c1;//消费者进程。
pc程序计数器和link ready; 就绪队列,link b_s1; s1阻塞队列,link b_s2; s2阻塞队列五、实验源代码:分为四个头文件1、a.h头文件代码如下:#include #include #include /* malloc()等 */ #include /* INT_MAX等 */ #include /* EOF(=^Z或F6),NULL */ #include /* atoi() */ #include /* eof() */ #include /* floor(),ceil(),abs() */ #include /* exit() */ #include using namespace std; #include #define BUF 10 //缓存的大小 #define MAX 20 //最大可以输入的字符2、b.h头文件代码如下://数据结构的定义和全局变量typedef struct Pcb{ char name[10]; //进程名 char state[10]; //运行状态 char reason[10]; //若阻塞,其原因 int breakp; //断点保护 struct Pcb *next; //阻塞时的顺序}Pcb,*link;int s1,s2; //信号量link p1;//生产者进程link c1;//消费者进程char str[MAX]; //输入的字符串char buffer[BUF]; //缓冲池int len; //输入长度int sp=0; //string的指针int in=0; //生产者指针int out=0; //消费者指针char temp; //供打印的临时产品char rec_p[MAX];//生产记录int rp1=0;//生产记录指针char rec_c[MAX];//消费记录int rp2=0;//消费记录指针link ready; //就绪队列link b_s1; //s1阻塞队列link b_s2; //s2阻塞队列int pc; //程序计数器int count; //字符计数器int con_cnt; //消费计数器3、c.h头文件代码如下:void init(); //初始化void p(int s); //P操作void v(int s); //V操作void block(int s);//阻塞函数void wakeup(int s);//唤醒函数void control(); //处理机调度void processor();//处理机执行void print(); //打印函数void init(){ //初始化 s1=BUF; s2=0; p1=(link)malloc(sizeof(Pcb));//建立新的结点,并初始化为生产者 strcpy(p1->name,"Producer"); strcpy(p1->state,"Ready"); strcpy(p1->reason,"Null"); p1->breakp=0; p1->next=NULL; c1=(link)malloc(sizeof(Pcb));//建立新的结点,并初始化为消费者 strcpy(c1->name,"Consumer"); strcpy(c1->state,"Ready"); strcpy(c1->reason,"Null"); c1->breakp=0; c1->next=NULL; ready=p1; ready->next=c1;//初始化为生产进程在前,消费进程在后 c1->next=NULL; b_s1=NULL; b_s2=NULL;//阻塞进程为NULL pc=0; con_cnt=0; //消费计数器}void p(int s){ if(s==1){ //p(s1) s1--; if(s1<0) block(1); //阻塞当前生产进程 else{ printf("\t* s1信号申请成功!\n"); ready->breakp=pc; //保存断点 } } else{ //p(s2) s2--; if(s2<0) block(2);//阻塞当前消费进程 else{ printf("\t* s2信号申请成功!\n"); ready->breakp=pc; //保存断点 } }}void v(int s){ if(s==1){ //v(s1) s1++; if(s1<=0) wakeup(1); //唤醒生产进程 ready->breakp=pc; //保存断点 } else{ //v(s2) s2++; if(s2<=0) wakeup(2);//唤醒消费进程 ready->breakp=pc; //保存断点 }}void block(int s){//阻塞函数的定义 link p; int num1=0; int num2=0; if(s==1){//生产进程 strcpy(p1->state,"Block");//改变状态 strcpy(p1->reason,"S1");//说明原因 p=b_s1; while(p){ num1++; p=p->next;//p的值为NULL,表示队尾 } if(!b_s1) b_s1=p1; else p=p1; p1->next=NULL; printf("\t* p1生产进程阻塞了!\n"); ready->breakp=pc; //保存断点 ready=ready->next;//在就绪队列中去掉,指向下一个 num1++; } else{//消费进程 strcpy(c1->state,"Block"); strcpy(c1->reason,"S2"); p=b_s2; while(p){ num2++; p=p->next;//p的值为NULL,表示队尾 } if(!b_s2) b_s2=c1; else p=c1; ready->breakp=pc; //保存断点 ready=ready->next;//在就绪队列中去掉,指向下一个 c1->next=NULL; printf("\t* c1消费进程阻塞了!\n"); num2++; } printf("\t* 阻塞的生产进程个数为:%d\n",num1); printf("\t* 阻塞的消费进程个数为:%d\n",num2);}void wakeup(int s){//唤醒函数的定义 link p; link q=ready; if(s==1){ //唤醒b_s1队首进程,生产进程队列 p=b_s1; b_s1=b_s1->next;//阻塞指针指向下一个阻塞进程 strcpy(p->state,"Ready"); strcpy(p->reason,"Null"); while(q)//插入就绪队列 q=q->next; q=p; p->next=NULL; printf("\t* p1生产进程唤醒了!\n"); } else{ //唤醒b_s2队首进程,消费进程队列 p=b_s2; b_s2=b_s2->next;//阻塞指针指向下一个阻塞进程 strcpy(p->state,"Ready"); strcpy(p->reason,"Null"); while(q->next)//插入就绪队列 q=q->next; q->next=p; p->next=NULL; printf("\t* c1消费进程唤醒了!\n"); }}void control() //处理器调度程序{ int rd; int num=0; link p=ready; if(ready==NULL) //若无就绪进程,结束 return; while(p) //统计就绪进程个数 { num++; p=p->next;//最终p变为NULL } printf("\t* 就绪进程个数为:%d\n",num); time_t t; srand((unsigned) time(&t)); rd=rand()%num;//随机函数产生随机数 if(rd==1){ p=ready; ready=ready->next; ready->next=p; p->next=NULL; strcpy(ready->state,"Run"); strcpy(ready->next->state,"Ready"); } else strcpy(ready-。