#include <stdio.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/types.h> #include <time.h> #include <stdlib.h> #include <sys/shm.h> int *buf; int n;//库存 int shpid;//共享存储区标识 int in=0,out=0; int empty,full,mutex1,mutex2;//信号量标识 pid_t pid; int newsem(int initVal){//——创建新的信号量,初值为initVal,完成后返回信号量的ID(typedef int MySem;) int r; int sem; sem=semget(0,1,IPC_CREAT|0666);//产生信号量标识 r=semctl(sem,0,SETVAL,initVal);//为指定信号量赋值,赋值成功为正,赋值失败为-1 return sem;//获得信号量标识 } void psem(int semID){//——对ID为semID的信号量做p //struct sembuf buf1=(0,-1,0); //int r=semop(semID,buf1,1); struct sembuf s; s.sem_num=0; s.sem_op=-1; s.sem_flg=0; int r=semop(semID,&s,1); } void vsem(int semID){//——对ID为semID的信号量做v //struct sembuf buf2=(0,1,0); //int r=semop(semID,buf2,1); struct sembuf s; s.sem_num=0; s.sem_op=1; s.sem_flg=0; int r=semop(semID,&s,1); } void freesem(int semID){//——注销ID为semID的信号量 int r; r=semctl(semID,0,IPC_RMID); } void init(){//请求用户输入仓库库存,然后申请并初始化共享存储区(仓库数组和变量in、out),以及所各种信号量 printf("read"); scanf("%d",&n); shpid=shmget(0,sizeof(int)*(n),IPC_CREAT|0666);//n+in+out,产生共享区标识 buf=(int*)shmat(shpid,0,0);//将共享存储区映射到用户进程空间 empty=newsem(n); full=newsem(0); mutex1=newsem(1);//生产者互斥 mutex2=newsem(1);//消费者互斥 } void pro(pid_t pid){//生产一个物品 printf("<P> <%d> started.\n",getpid());//开始时在屏幕显示<进程类型(P或C)> <进程id> started. int set=buf[in];//从0开始存 psem(empty); psem(mutex1); buf[in]=1;//所生产的一个物品存入buf[in] in=(in+1)%n; printf("P <%d> put an item to <%d>.\n",getpid(),set);//结束时Pro()显示:P <进程id> put an item to <仓库位置>. vsem(mutex1); vsem(full); } void con(pid_t pid){ printf("<C> <%d> started.\n",getpid()); int set=buf[out];//从0开始取 psem(full); psem(mutex2); buf[out]=0;//从buf[out]取出一个物品 out=(out+1)%n; printf("C <%d> put an item to <%d>.\n",getpid(),set); vsem(mutex2); vsem(empty); } int main(){ init(); while(1) { pid=fork();//建立一个新进程(子进程) ,返回子进程的进程ID 在子进程中返回0 if(pid==0)//子进程 { if(rand()%2)//0,1 pro(pid); else con(pid); break; } else //父进程 sleep(rand()%3); } int x1=shmdt(0); int x2=shmctl(shpid,IPC_RMID,0); return 0; }
gcc a.c
./a.out