进程同步和通信 -生产者和消费者问题模拟

程序说明:这是我自己修改后的操作系统实验题目(这里有许多创新之处,至少对我而言)。
缓冲区可以容纳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;
}

 

 

转载于:https://www.cnblogs.com/Xbert/p/4514264.html

1. 目的: 调试、修改、运行模拟程序,通过形象化的状态显示,使学生理解进程的概念,了解同步和通信的过程,掌握进程通信和同步的机制,特别是利用缓冲区进行同步和通信的过程。通过补充新功能,使学生能灵活运用相关知识,培养创新能力。 2. 内容及要求: 1) 调试、运行模拟程序。 2) 发现并修改程序中不完善的地方。 3) 修改程序,使用随机数控制创建生产者消费者的过程。 4) 在原来程序的基础上,加入缓冲区的写互斥控制功能,模拟多个进程存取一个公共缓冲区,当有进程正在写缓冲区时,其他要访问该缓冲区的进程必须等待,当有进程正在读取缓冲区时,其他要求读取的进程可以访问,而要求写的进程应该等待。 5) 完成1)、2)、3)功能的,得基本分,完成4)功能的加2分,有其它功能改进的再加2分 3. 程序说明:   本程序是模拟两个进程,生产者(producer)和消费者(Consumer)工作。生产者每次产生一个数据,送入缓冲区中。消费者每次从缓冲区中取走一个数据。缓冲区可以容纳8个数据。因为缓冲区是有限的,因此当其满了时生产者进程应该等待,而空时,消费者进程应该等待;当生产者向缓冲区放入了一个数据,应唤醒正在等待的消费者进程,同样,当消费者取走一个数据后,应唤醒正在等待的生产者进程。就是生产者消费者之间的同步。   每次写入和读出数据时,都将读和写指针加一。当读写指针同样时,又一起退回起点。当写指针指向最后时,生产者就等待。当读指针为零时,再次要读取的消费者也应该等待。 为简单起见,每次产生的数据为0-99的整数,从0开始,顺序递增。两个进程的调度是通过运行者使用键盘来实现的。 4. 程序使用的数据结构 进程控制块:包括进程名,进程状态和执行次数。 缓冲区:一个整数数组。 缓冲区说明块:包括类型,读指针,写指针,读等待指针和写等待指针。 5. 程序使用说明   启动程序后,如果使用'p'键则运行一次生产者进程,使用'c'键则运行一次消费者进程。通过屏幕可以观察到两个进程的状态和缓冲区变化的情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值