icendjoennhdind 2022-11-27 02:18 采纳率: 75%
浏览 106
已结题

Linux环境生产者消费者问题

在Linux环境下编写生产者和消费者程序,要求:

  1. 生产者和消费者两个程序,共用一个仓库,仓库是一个普通文件(/tmp/store),容量为100个字节;
  2. 生产者生产资源放进仓库,消费者则从仓库中消费资源;资源为数字字符“0~9”,一个资源就是一个数字,10个数字循环生成;
  3. 生产者创建仓库(/tmp/store),间隔1s生产一个资源,当仓库满了(资源数量达到100个)的时候,生产者不能继续生产;消费者间隔2s消费一个资源,当仓库为空的时候,消费者不能继续消费;
  4. 消费者每次消费1个资源,首先打印出消耗之前仓库中的资源数量和空位的数量,然后打印出消耗之后仓库中的资源数量和空位的数量,并打印出所消耗的资源内容;
  5. 生产者每次生产1个资源,先打印出生产之前仓库中的资源数量和空位的数量,然后打印出生产之后仓库中的资源数量和空位的数量,并打印出所生产的资源内容。
  6. 消费者消费资源后需要把已经消费的资源从仓库里删除;
  7. 用信号量实现进程的同步和互斥。
    【提示】可以用1个或多个信号量,semget()、semctl()函数、semop()函数的使用,包含对store文件的读写删改
  • 写回答

2条回答 默认 最新

  • 关注

    生产者:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <assert.h>
    #include <sys/sem.h>
    
    int semid;
    
    union semun
    {
        int val;
    };
    //初始化
    void sem_init()
    {
            //semget:创建一个新信号量或者获取一个已有的信号量的键
            semid=semget((key_t)1234,1,IPC_CREAT|IPC_EXCL|0600);//1234:房间号,0600->文件权限
            if(semid==-1)   //全新创建失败,获取已经存在的信号量
            {
                    semid=semget((key_t)1234,1,0600);
                    if(semid==-1)
                    {
                            perror("semget error");
                    }
                    else
                    {
                            //初始化
                            union semun a;//定义联合体
                            a.val=1;//初始化设置为1,假设刚开始可以使用
                            //semctl:用来直接控制信号量信息
                            if(semctl(semid,0,SETVAL,a)==-1)//编号从0开始
                            {
                                    perror("semctl init error");
                            }
                    }
            }
    }
    
    void sem_p()//p操作
    {
            struct sembuf buf;
            buf.sem_num=0;
            buf.sem_op=-1;
            buf.sem_flg=SEM_UNDO;//一般都这样设置,是让操作系统记住使用了P操作
            //semop:对信号量进行改变,做p或者v操作
            if(semop(semid,&buf,1)==-1)//1:长度,只有一个信号量
                    perror("p perror");
    }
    
    void sem_v()//v操作
    {
            struct sembuf buf;
            buf.sem_num=0;
            buf.sem_op=1;
            buf.sem_flg=SEM_UNDO;//一般都这样设置,是让操作系统记住使用了P操作
            if(semop(semid,&buf,1)==-1)//1:长度,只有一个信号量
                    perror("v perror");
    }
    //销毁
    void sem_destory()
    {
            if(semctl(semid,0,IPC_RMID)==-1)
                    perror("destory sem error");
    }
    
    int main()
    {
            int i=0;
            int size=0;
            FILE* fp;
            //char sym[]={'0','1','2','3','4','5','6','7','8','9'};
            char ch;
    
            //信号量初始化
            sem_init();
            printf("This is the producer...\n");
            while(1)
            {
                sem_p();//
                fp = fopen("/tmp/store","a");
                size = ftell(fp); //
                printf("Before produce, resource number:%d,left position:%d\n",size,100-size);
    
                if(size >=100)
                {
                    printf("The store is full! resource number:%d,left position:%d\n",size,100-size);
                    fclose(fp);
                }else
                {
                    ch = (char)('0'+i%10);
                    printf("After produce, resource number:%d,left position:%d, ",size+1,99-size);
                    printf("new resource:%c\n",ch);
                    i++;
                    fwrite(&ch,1,1,fp);
                    fclose(fp);
                }
                sem_v();
                sleep(1);
            }
            sem_destory();
    }
    
    
    

    消费者:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <assert.h>
    #include <sys/sem.h>
    
    int semid;
    
    union semun
    {
        int val;
    };
    //初始化
    void sem_init()
    {
            //semget:创建一个新信号量或者获取一个已有的信号量的键
            semid=semget((key_t)1234,1,IPC_CREAT|IPC_EXCL|0600);//1234:房间号,0600->文件权限
            if(semid==-1)   //全新创建失败,获取已经存在的信号量
            {
                    semid=semget((key_t)1234,1,0600);
                    if(semid==-1)
                    {
                            perror("semget error");
                    }
                    else
                    {
                            //初始化
                            union semun a;//定义联合体
                            a.val=1;//初始化设置为1,假设刚开始可以使用
                            //semctl:用来直接控制信号量信息
                            if(semctl(semid,0,SETVAL,a)==-1)//编号从0开始
                            {
                                    perror("semctl init error");
                            }
                    }
            }
    }
    
    void sem_p()//p操作
    {
            struct sembuf buf;
            buf.sem_num=0;
            buf.sem_op=-1;
            buf.sem_flg=SEM_UNDO;//一般都这样设置,是让操作系统记住使用了P操作
            //semop:对信号量进行改变,做p或者v操作
            if(semop(semid,&buf,1)==-1)//1:长度,只有一个信号量
                    perror("p perror");
    }
    
    void sem_v()//v操作
    {
            struct sembuf buf;
            buf.sem_num=0;
            buf.sem_op=1;
            buf.sem_flg=SEM_UNDO;//一般都这样设置,是让操作系统记住使用了P操作
            if(semop(semid,&buf,1)==-1)//1:长度,只有一个信号量
                    perror("v perror");
    }
    //销毁
    void sem_destory()
    {
            if(semctl(semid,0,IPC_RMID)==-1)
                    perror("destory sem error");
    }
    
    int main()
    {
            int size=0;
            FILE* fp,*fp2;
            char ch[110]={0};
            int len,i;
            //信号量初始化
            sem_init();
            printf("This is a customer...\n");
            while(1)
            {
                sem_p();//
                memset(ch,0,110);
                fp = fopen("/tmp/store","r");
                fseek(fp,0,SEEK_END);
                size = ftell(fp); //
                fseek(fp,0,SEEK_SET);
                fread(ch,1,size,fp);
                fclose(fp);
    
                /*for(i=0;i<size;i++)
                    printf("%c ",ch[i]);
                printf("\n");*/
    
                len = strlen(ch);
                ch[len] = 0;
    
                printf("Before use, resource number:%d, left position:%d\n",len,100-len);
                if(len == 0)
                {
                    printf("The store is empty!\n");
                }
                else
                {
                    printf("After use, resource number:%d, left position:%d, ",len-1,101-len);
                    printf("the resource:%c\n",ch[0]);
                    fp2 = fopen("/tmp/store","w");
                    fwrite(ch+1,1,len-1,fp2);
                    fclose(fp2);
                }
                sem_v();
                sleep(2);
            }
            sem_destory();
    }
    
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 11月29日
  • 已采纳回答 11月29日
  • 创建了问题 11月27日

悬赏问题

  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效