zoukankan      html  css  js  c++  java
  • 进程同步和通信 -生产者和消费者问题模拟

    程序说明:这是我自己修改后的操作系统实验题目(这里有许多创新之处,至少对我而言)。
    缓冲区可以容纳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("
     ****************************");
            printf("
     产品 %d 已分发给待消费者了. ",out);
            printf("
     待消费的产品数为:%d",--i_consume);
            printf("
     ****************************
    ");
            return 0;
        }
        printf("
     PRODUCER Running !	Product %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("
     ****************************");
            printf("
     没有产品了,消费者进入队列. ");
            printf("
     待消费的产品数为:%d",i_consume);
            printf("
     ****************************
    ");
            sum--;
            return 0;
        }
        if(sum>PIPESIZE) //产品总数大于8
        {
            printf("
     CONSUMER Running !	Consumer %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("
     CONSUMER Running !	Consumer %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("
     ");
        for(i=0; i<PIPESIZE; i++) printf("------ ");
        printf("
     |");
        for(i=0; i<PIPESIZE; i++)
            if(pipe[i][1]==1) printf(" %2d |",pipe[i][0]);
            else printf(" |");
        printf("
     ");
        for(i=0; i<PIPESIZE; i++) printf("------ ");
        printf("
    ");
        printf("
     writeptr = %d,	readptr = %d ",tb.writeptr,tb.readptr);
        if(sum>PIPESIZE)
        {
            printf("
     生产者缓冲区: ");
            for(i=0; i<i_prodece; i++)
                printf("%2d |",pipe_produce[i]);
            printf("
    ");
        }
    }
    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";
        process[CONSUMER].name = "Consumer";
        output = 0;
        printf("Now starting the program!
    ");
        printf("Press 'p' to run PRODUCER, press 'c' to run CONSUMER.
    ");
        printf("Press 'e' to exit from the program.
    ");
        for(i=0; i<1000; i++)
        {
            printf("
     +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     ");
            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!
    ");
                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;
    }
  • 相关阅读:
    Spark 性能相关参数配置详解-压缩与序列化篇
    Spark 性能相关参数配置详解-shuffle篇
    html5 手风琴菜单
    小知识
    android Service服务(二)
    android Service服务简介(一)
    初学Node.js -环境搭建
    jsp传参 servlet接收中文乱码问题
    android xml实现animation 4种动画效果
    android Volley+Gson的使用
  • 原文地址:https://www.cnblogs.com/Xbert/p/4514264.html
Copyright © 2011-2022 走看看