操作系统实验3

操作系统实验三
模拟“生产者-消费者”进程实现

include <sys/mman.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#define MAXSEM 5
/*模拟生产者和消费者问题*/ 
int fullid;
int emptyid;
int mutxid;

void main()
{
	struct sembuf P, V;//声明两个结构体P、V 
	union semun
	{
		int val;
		struct semid_ds *buf;
		ushort *array;
	} arg;
	/*声明四个共享主存*/
	int *array;//定义数组表示缓冲池
	int *sum;
	int *set;
	int *get;
	/*mmap:把文件内容映射到内存中,实现共享*/
	array = (int *)mmap(NULL, sizeof(int) * 5, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); //sizeof(int)*5,开辟一个能放5个的内存空间共享
	sum = (int *)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
	get = (int *)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
	set = (int *)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
	*sum = 0;
	*get = 0;
	*set = 0;
	/*semget:创建一个信号量集合或获取一个已经存在的信号量集*/ 
	fullid = semget(IPC_PRIVATE, 1, IPC_CREAT | 00666); //创建三个信号量集,信号量集中各有三个信号量,所有人都可以访问 
	emptyid = semget(IPC_PRIVATE, 1, IPC_CREAT | 00666);
	mutxid = semget(IPC_PRIVATE, 1, IPC_CREAT | 00666);
   /*semctl:赋初值,对信号量进行一系列控制*/
	arg.val = 0;
	if (semctl(fullid, 0, SETVAL, arg) == -1)//对fullid赋初值为0 
		perror("semctl semval error");
	arg.val = MAXSEM;
	if (semctl(emptyid, 0, SETVAL, arg) == -1)//对emptyid赋初值为maxsem 
		perror("semctl semval error");
	arg.val = 1;
	if (semctl(mutxid, 0, SETVAL, arg) == -1)//对互斥信号量赋初值1 
		perror("semctl semval error");

	V.sem_num = 0;//对具体的信号量的操作 
	V.sem_op = 1;
	V.sem_flg = SEM_UNDO;
	P.sem_num = 0;
	P.sem_op = -1;
	P.sem_flg = SEM_UNDO;
	
	if (fork() == 0)//一个子进程充当生产者进程 
	{ 
		while (*set < 20)
		{
			/*semop:对信号量仅从P、V操作,参数为信号量集标识符,sops,nsops*/
			semop(emptyid, &P, 1);			//同步P操作 
			semop(mutxid, &P, 1);		//互斥P操作 
			array[(*set) % MAXSEM] = *set + 1;//生产了一个,向缓冲池中放 
			printf("Producer %d\n", array[(*set) % MAXSEM]);//生产产品的标号+1 
			(*set)++;			  //指针下移 
			semop(mutxid, &V, 1); //互斥V操作 
			semop(fullid, &V, 1); //同步V操作 
		}
		sleep(2);//休眠两秒 
		printf("Producer is over\n");
		exit(0);
	}
	else
	{ 
		if (fork() == 0)//一个子进程充当消费者进程 
		{ 
			while (1)
			{
				semop(fullid, &P, 1); //同步P操作 
				semop(mutxid, &P, 1);//互斥P操作 
				if (*get < 20){//判断是否所有产品都被消费了 
					*sum += array[(*get) % MAXSEM];
					printf("The consumerA Get Number %d\n", array[(*get) % MAXSEM]);//消费者A取了多少个 
					(*get)++;//指针下移 
					if (*get == 20){//判断此次消费是不是最后一次消费 
						printf("The sum is %d\n", *sum);
					}
				}
				semop(mutxid, &V, 1);  //互斥V操作 
				semop(emptyid, &V, 1); //同步V操作 
				if (*get == 20)
				{
					break;
				}
			}
			printf("ConsumerA is over\n");
			exit(0);
		}
		else
		{
			if (fork() == 0)//另一个子进程充当消费者进程,两个消费者不能同时向外取 
			{ 
				while (1)//和上面同理 
				{
					semop(fullid, &P, 1); 
					semop(mutxid, &P, 1);
					if (*get < 20){
						*sum += array[(*get) % MAXSEM];
						printf("The consumerB Get Number %d\n", array[(*get) % MAXSEM]);
						(*get)++;
						if (*get == 20){
							printf("The sum is %d\n", *sum);
						}
					}
					semop(mutxid, &V, 1); 
					semop(emptyid, &V, 1); 
					if (*get == 20){
						break;
					}
				}
				printf("ConsumerB is over\n");
				exit(0);
			}
			else{
				sleep(3);
				exit(0);
			}
		}
	}
}

/*fork()>0 父进程 fork()=0 子进程 

运行后截图:

posted @   星星盛开的地方  阅读(185)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示