操作系统共享内存消费者生产者循环队列

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
在linux的ubuntu下运行
头文件
shmdata.h

#ifndef _SHMDATA_H_HEADER
#define _SHMDATA_H_HEADER
#include "stdio.h"
#include "string.h"
#include "stdbool.h"
#define TEXT_LEN 10
#define MAX_SIZE 5

typedef struct queue {//循环队列
    char buf[TEXT_LEN * MAX_SIZE];//字符串数组
    int front;//队头指针,读指针
    int rear;//队尾指针,写指针
    int readlock;//值为1时读的临界区内存可访问,为0时不可访问
    int writelock;//值为1时写的临界区内存可访问,为0时不可访问
    int fullnum;//队列中写入字符串的内存单元个数
    int emptynum;//队列中为空的内存单元个数
    int firstbuild;//第一次创建队列的标志位,创建完成为1
} Queue;
bool enqueue(Queue *q, const char *data, size_t len);

bool dequeue(Queue *q, char *data);

void init_queue(Queue *q) {
    q->front = 0;
    q->rear = 0;
    q->readlock=0;
    q->writelock=1;
    q->fullnum=0;
    q->emptynum=1;
    q->firstbuild=1;
    memset(q->buf, 0, TEXT_LEN * MAX_SIZE);
}

bool enqueue(Queue *q, const char *data, size_t len) {
    if (len > TEXT_LEN || len <= 0) {
        puts("ERROR: the length of data is not supported!");
        return false;
    } else {
            strncpy(q->buf + q->rear * TEXT_LEN, data, len);
            q->rear = (q->rear + 1) % MAX_SIZE;
            return true;
    	   }
}

bool dequeue(Queue *q, char *data) {
        strncpy(data, q->buf + q->front * TEXT_LEN, TEXT_LEN);
        q->front = (q->front + 1) % MAX_SIZE;  
        return true;
}
#endif

consumer.c

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/shm.h>
#include "shmdata.h"
int main()
{  
    int running = 1;//程序是否继续运行的标志  
    void *shm = NULL;//分配的共享内存的原始首地址   
    int shmid;//共享内存标识符,创建共享内存 
    //寻找与生产者的共享内存,成功返回共享内存的ID,出错返回-1  
    shmid = shmget((key_t)1231, sizeof(Queue), 0666|IPC_CREAT);
    if(shmid == -1)
    {      
        fprintf(stderr, "shmget failed\n");
        exit(EXIT_FAILURE);
    } 
    //将共享内存连接到当前进程的地址空间(挂接操作)
    //成功返回共享存储段的指针,出错返回-1
    shm = shmat(shmid, 0, 0);
    if(shm == (void*)-1)   
    {  
        fprintf(stderr, "shmat failed\n"); 
        exit(EXIT_FAILURE);
    }  
    //将内存地址赋值给队列  
    Queue *q= (Queue*)shm;   
    char ret[TEXT_LEN];
    //读进程循环执行
    while(running)
    {          
        if(q->readlock=1&&q->fullnum!=0)
        {  
            q->fullnum=q->fullnum-1;//申请一个存放数据的内存单元
            q->readlock=0;//占用读的临界区内存空间
            dequeue(q, ret); //消费者将内容从队头读出
            if(strncmp(ret,"end",3)==0)//如果读到结束标志
             {
             	q->readlock=1; // 释放读的临界区内存空间
             	q->emptynum=q->emptynum-1;//队列减少一个存放数据的内存单元
            	running=0;
             }
            printf("Consume the data: %s",ret);            
            q->readlock=1; // 释放读的临界区内存空间
            q->emptynum=q->emptynum-1;//队列减少一个存放数据的内存单元
            usleep(rand()%10000); //进程被阻塞0us到10ms之间的一个随机数,CPU运行其他消费者进程
        }      
        else//有其他消费者进程在CPU运行,不能读取数据     
            usleep(rand()%10000);  //进程被阻塞0us到10ms之间的一个随机数,CPU运行其他消费者进程
    }   
    //把共享内存从当前进程中分离
    if(shmdt(shm) == -1)   
    {      
        fprintf(stderr, "shmdt failed\n");     
        exit(EXIT_FAILURE);
    } 
    exit(EXIT_SUCCESS);
}

producer.c

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include "shmdata.h"
int main()
{  
    int running = 1;  //控制进程可以进行循环写操作 
    void *shm = NULL;  //分配的共享内存的原始首地址
    char buffer[BUFSIZ + 1];//用于保存输入的文本
    int shmid; //共享内存的id
    //创建共享内存,成功返回共享内存的ID,出错返回-1
    shmid = shmget((key_t)1231, sizeof(struct queue), 0666|IPC_CREAT);
    if(shmid == -1)
    {  
        fprintf(stderr, "shmget failed\n");
        exit(EXIT_FAILURE);
    }   
    //将共享内存连接到当前进程的地址空间(挂接操作)
    //成功返回共享存储段的指针,出错返回-1
    shm = shmat(shmid, (void*)0, 0);   
    if(shm == (void*)-1)
    {  
        fprintf(stderr, "shmat failed\n");     
        exit(EXIT_FAILURE);
    }  
    //将内存地址赋值给队列   
    struct queue* q= (Queue*)shm; 
    //初始化队列
    if(q->firstbuild!=1)
    	{
    		init_queue(q);
    		printf("队列初始化\n");
    	}
    //写进程循环执行 
    while(running)
    {  
    	//写的临界区不可用或者队列已满       
        while(q->writelock == 0||q->fullnum==MAX_SIZE)     
        {          
            if(q->fullnum==MAX_SIZE)
            	printf("Queue full\n");
            usleep(rand()%10000);//因队列满进程被阻塞0us到10ms之间的一个随机数,等待消费者消费      
            printf("Waiting...\n");
        }
        q->emptynum=q->emptynum-1;//申请一个空的单元             
	q->writelock=0;//占用写的临界区内存空间
	printf("Produce the data: "); 
	fgets(buffer, BUFSIZ, stdin);//获取数据到缓冲区
        enqueue(q,buffer,TEXT_LEN);  //向写临界区(队尾)中写入数据
        q->writelock = 1;//释放写的临界区内存空间         
        q->fullnum=q->fullnum+1; //队尾增加一个存放数据的单元
        //如果存放数据的单元既是队头又是队尾
        //则在写操作完毕后释放读的临界区内存资源
        if(q->fullnum==1)
           q->readlock=1;   
        usleep(rand()%10000); //执行写操作一次后,进程被阻塞0us到10ms之间的一个随机数,CPU运行其他写进程
        //输入了end,退出循环(程序)  
        if(strncmp(buffer, "end", 3) == 0)         
            running = 0;   
    }   
    //把共享内存从当前进程中分离
    if(shmdt(shm) == -1)   
    {      
        fprintf(stderr, "shmdt failed\n");     
        exit(EXIT_FAILURE);
    }  
    exit(EXIT_SUCCESS);
}

删除共享内存
delm.c
delm.c运行结果:
先运行生产者,再运行消费者
一个生产者,队列满:
运行结果:一个生产者,队列满一个生产者,一个消费者:
运行结果:一个生产者,一个消费者多个生产者,多个消费者:
用sleep()进行阻塞的测试结果:
用sleep()用usleep()进行阻塞的测试结果:
用usleep()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值