信号量与共享存储区(操作系统实验三)

实验目的:

1.熟悉Linux环境下的多进程编程

2.熟悉Linux的信号量与共享存储区的使用

3.加深对生产者/消费者(PC)问题的理解

实验环境:

Ubuntu 12.4(32位,简体中文)

实验内容:

1.编写程序,构建父进程逻辑与紫子进程逻辑框架;
2.对信号量操作进行再次封装,实现以下函数:

MySem newsem(int initVal)
:创建新的信号量,初值为initVal,完成后返回信号量的ID(typedef int MySem;)

void psem(MySem semID):对ID为semID的信号量做p

void vsem(MySemsemID):对ID为semID的信号量做v

void freesem(MySemsemID):注销ID为semID的信号量

3.在init()中添加代码,请求用户输入仓库库存,然后申请并初始化共享存储区(仓库数组和变量in、out),以及所各种信号量。

4.在Pro()和Con()中添加代码,完成复杂PC问题(多生产者、多消费者)的模拟。
其中Pro()和Con()开始时在屏幕显示
<进程类型(P或C)> <进程id> started.
结束时Pro()显示:P <进程id> put an item to <仓库位置>.
Con()显示:C <进程id> got an item from <仓库位置>.

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<time.h>
#include<sys/shm.h>
#include<sys/sem.h>
#include<sys/types.h>
#include<sys/ipc.h>
#define PRO 1
#define CON 0
#define p -1
#define v +1
int empty,full,mutex1,mutex2;
int *buf;
int newsem(int intval)		//新建信号量
{
	int r,semID;
	semID=semget(0,1,IPC_CREATE|0666);	//创建新的信号量集并可读写
	r=semctl(semID,0,SETVAL,intval);	//对制定信号量赋值为intval,若成功则,返回一个正数,否则返回一个负数;
	return semID;
}
void psem(int semID)			//对ID为semID的信号量做p操作;
{
	struct sembuf s;
	s.sem_num=0;			//欲操作的信号量在信号集中的编号
	s.sem_op=p;			//信号量PV操作的增量
	s.sem_flg=0;			//额外选项标识(0表示无额外设置,IPC_NOWAIT表示不允许阻塞,SEM_UNDO表示进程结束时回复信号量等)

	int r=semop(semID,&s,1);	//对指定的semID信号量执行p操作
}
void vsem(int semID)			//对ID为semID的信号量做操作;
{
	struct sembuf s;
        s.sem_num=0;                    //欲操作的信号量在信号集中的编号
        s.sem_op=v;                     //信号量PV操作的增量
        s.sem_flg=0;                    //额外选项标识(0表示无额外设置,$

        int r=semop(semID,&s,1);        //对指定的semID信号量执行v操作
}
void freesem(int semID)
{
	int r;
	r=semctl(semID,0,IPC_RMID);	//IPC_RMID:表示注销信号量集,不需要参数;

}
int init(int n)
{
	int shpid;
	shpid=shmget(0,sizeof(int)*(n+2),IPC_CREAT|0666);//create共享存储区+2 in out
	buf=(int *)shmat(shpid,0,0);	//将共享存储区映射到用户进程空间;
	empty=newsem(n);		//缓冲区单元格有n个,初始化标记为null,允许生产者进程一开始就连续执行k次;
	full=newsem(0);			//初始时,没有满标记单元格,置初值full=0;
	mutex1=newsem(1);		//生产者的互斥;
	mutex2=newsem(1);		//消费者的互斥;
	buf[n]=0;			//缓冲区单元格in;
	buf[n+1]=0;			//缓冲区单元格out;
	return shpid;			//存储区id;
}
void pro()
{
}
void con()
{
}
int main()
{
	int t,k,n;
	printf("请输入仓库库存n:\n");
	scanf("%d",&n);
	int shpid=init(n);
	k=rand()%1+1;
	pid_t pid;		//定义进程标示符;
	while(1)
	{
		srand((unsigned)time(NULL));	//每次置随机数种子;
		pid=fork();			//建立一个新的子进程,在父进程返回的时子进程的ID,在子进程返回0;
		if(pid==0)	//子进程;
		{
			t=rand()%2;	//0,1
			if(t==PRO)
				pro(pid,n);
			else if(t==CON)
				con(pid,n);
			return 0;
		}
		else		//父进程;
			sleep(rand()%3);
	}
	int x1=shmdt(0);	//断开已有的映射
	int x2=shctl(shpid,IPC_RMID,0);
	return 0;
}

未完待续;

posted @ 2018-05-26 00:21  heihuifei  阅读(699)  评论(0编辑  收藏  举报