程序说明:这是我自己修改后的操作系统实验题目(这里有许多创新之处,至少对我而言)。
缓冲区可以容纳8个数据;因为缓冲区是有限的,因此当其满了时生产者进程应该等待;当消费者取走一个数据后,应唤醒正在等待的生产者进程;
当缓冲区空时,消费者进程应该等待;当生产者向缓冲区放入了一个数据时,应唤醒正在等待的消费者进程。这就是生产者和消费者之间的同步。
每次写入和读出数据时,都将读和写指针加一。当指针到达缓冲区尾,重新将指针退回起点;
为简单起见,每次产生的数据为0-99的整数,从0开始,顺序递增;
两个进程的调度是通过运行者使用键盘来实现的。
启动程序后,如果使用‘p’键则运行一次生产者进程;
使用‘c’键则运行一次消费者进程;
使用‘e’键则退出程序;
通过屏幕可以观察到两个进程的状态和缓冲区变化的情况。
程序源代码如下:
#include <stdio.h> #include<stdlib.h> #define PIPESIZE 8 #define PRODUCER 0 #define CONSUMER 1 #define PIPE_PRODUCER_SIZE 40 struct pcb { char *name; int statu; int time; int flag; //标识1为有产品,0为没有产品 }; // times of execution struct pipetype { char type; //生产者或消费者 int writeptr; int readptr; struct pcb *pointp; //write wait point struct pcb *pointc; }; //read wait point int pipe[PIPESIZE][2]; int pipe_produce[PIPE_PRODUCER_SIZE]; //生产者队列 int i_prodece=0; int i_consume=0; int sum=0;//产品总数 struct pipetype pipetb; struct pcb process[2]; int runp(int out,struct pcb p[],int pipe[][2],struct pipetype *tb,int t) //run producer { if(i_consume>0) //把产品分发给等待中的消费者 { printf("\n ****************************"); printf("\n 产品 %d 已分发给待消费者了. ",out); printf("\n 待消费的产品数为:%d",--i_consume); printf("\n ****************************\n"); return 0; } printf("\n PRODUCER Running !\tProduct %d ",out); if((tb->writeptr==tb->readptr)&&(pipe[(tb->writeptr+1)%8][1]==1)) { //pipe[8]已经填满,把产品存储在生产者队列中 pipe_produce[i_prodece]=out; i_prodece++; sum++; return 0; } pipe[tb->writeptr][0]=out; //out为产品标识 pipe[tb->writeptr][1]=1; //标识有产品 tb->writeptr++; tb->writeptr=(tb->writeptr%8); sum++; return 0; } int runc(struct pcb p[],int pipe[][2],struct pipetype *tb,int t) //run consumer { if(sum<=0) //消费者等待 { i_consume++; printf("\n ****************************"); printf("\n 没有产品了,消费者进入队列. "); printf("\n 待消费的产品数为:%d",i_consume); printf("\n ****************************\n"); sum--; return 0; } if(sum>PIPESIZE) //产品总数大于8 { printf("\n CONSUMER Running !\tConsumer %d ",pipe_produce[0]); pipe[tb->readptr][0]=pipe_produce[0]; pipe[tb->readptr][1]=1; tb->readptr++; tb->readptr=(tb->readptr%8); sum--; if(sum>8) for(int i=0; i<i_prodece; i++) pipe_produce[i]=pipe_produce[i+1]; i_prodece--; return 0; } if(sum==PIPESIZE) //重新定位开始生产的指针 tb->writeptr=tb->readptr; printf("\n CONSUMER Running !\tConsumer %d ",pipe[tb->readptr][0]); pipe[tb->readptr][1]=0; //已经消费掉 tb->readptr++; tb->readptr=(tb->readptr%8); sum--; return 0; } void prn(struct pcb p[],int pipe[][2],struct pipetype tb) { int i; printf("\n "); for(i=0; i<PIPESIZE; i++) printf("------ "); printf("\n |"); for(i=0; i<PIPESIZE; i++) if(pipe[i][1]==1) printf(" %2d |",pipe[i][0]); else printf(" |"); printf("\n "); for(i=0; i<PIPESIZE; i++) printf("------ "); printf("\n"); printf("\n writeptr = %d,\treadptr = %d ",tb.writeptr,tb.readptr); if(sum>PIPESIZE) { printf("\n 生产者缓冲区: "); for(i=0; i<i_prodece; i++) printf("%2d |",pipe_produce[i]); printf("\n"); } } int main() { int output,ret,i; char in[2]; pipetb.type = 'c'; pipetb.writeptr = 0; pipetb.readptr = 0; pipetb.pointp = pipetb.pointc = NULL; process[PRODUCER].name = "Producer\0"; process[CONSUMER].name = "Consumer\0"; output = 0; printf("Now starting the program!\n"); printf("Press 'p' to run PRODUCER, press 'c' to run CONSUMER.\n"); printf("Press 'e' to exit from the program.\n"); for(i=0; i<1000; i++) { printf("\n +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n "); in[0]='N'; while(in[0]=='N') { scanf("%s",in); if(in[0]!='e'&&in[0]!='p'&&in[0]!='c') in[0]='N'; } if(in[0]=='e') { printf("Program completed!\n"); exit(0); } if(in[0]=='p') { runp(output,process,pipe,&pipetb,PRODUCER); output = (output++)%100; } if(in[0]=='c') runc(process,pipe,&pipetb,CONSUMER); //消费一个产品 prn(process,pipe,pipetb); in[0]='N'; } return 0; }