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文件的读写删改

生产者:

#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();
}


您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!
PS:问答VIP年卡 【限时加赠:IT技术图书免费领】,了解详情>>> https://vip.csdn.net/askvip?utm_source=1146287632