使用信号量灯集同步三个进程操作共享内存打印ABC
head.h
#ifndef __SEM_H__
#define __SEM_H__
//创建信号灯集并初始化
int create_sem(int semcount);
//申请资源 P操作
int P(int semid,int semno);
//释放资源 V操作
int V(int semid,int semno);
//删除信号灯集
int delete_sem(int semid);
#endif
test.c
#include<my_head.h>
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
//初始化信号灯集函数
int init_sem(int semid,int semno)
{
union semun us;
printf("请输入第%d号灯的初始值:",semno);
scanf("%d",&us.val);
getchar();
if(semctl(semid,semno,SETVAL,us) == -1)
{
perror("init_sem error");
return -1;
}
return 0;
}
//创建信号灯集并初始化
int create_sem(int semcount)
{
key_t key = ftok("/",520);
if(key == -1)
{
perror("ftok error");
return -1;
}
int semid = semget(key,semcount,IPC_CREAT|IPC_EXCL|0666);
if(semid == -1)
{
if(errno == EEXIST)
{
semid = semget(key,semcount,IPC_CREAT);
return semid;
}
perror("semget error");
return -1;
}
for(int i=0;i<semcount;i++)
{
init_sem(semid,i);
}
return semid;
}
//申请资源 P操作
int P(int semid,int semno)
{
struct sembuf buf;
buf.sem_num = semno;
buf.sem_op = -1;
buf.sem_flg = 0;
if(semop(semid,&buf,1) == -1)
{
perror("p error");
return -1;
}
return 0;
}
//释放资源 V操作
int V(int semid,int semno)
{
struct sembuf buf;
buf.sem_num = semno;
buf.sem_op = 1;
buf.sem_flg = 0;
if(semop(semid,&buf,1) == -1)
{
perror("v error");
return -1;
}
return 0;
}
//删除信号灯集
int delete_sem(int semid)
{
if(semctl(semid,0,IPC_RMID) == -1)
{
perror("delete_sem error");
return -1;
}
return 0;
}
A.c
#include<my_head.h>
#define PAGE_SIZE 4096
#include "head.h"
int main(int argc, const char *argv[])
{
//创建信号灯集并初始化
int semid = create_sem(3);
//创建key值
key_t key = ftok("/",1314);
if(key == -1)
{
perror("ftok");
return -1;
}
//用key值创建一个共享内存,返回shmid
int shmid = shmget(key,PAGE_SIZE,IPC_CREAT|0666);
if(shmid == -1)
{
perror("shmget error");
return -1;
}
//映射共享内存到用户空间
char *addr = shmat(shmid,NULL,0);
if(addr == (void *)-1)
{
perror("shmat error");
return -1;
}
//使用共享内存
int count = 5;
while(count -- )
{
//先打印一个A
puts("A");
//p操作申请0号灯
P(semid,0);
//存放数据B
strcpy(addr,"B");
//v操作释放1号灯
V(semid,1);
}
//取消共享内存映射
if(shmdt(addr) == -1)
{
perror("shmdt error");
return -1;
}
return 0;
}
B.c
#include<my_head.h>
#define PAGE_SIZE 4096
#include "head.h"
int main(int argc, const char *argv[])
{
//创建信号灯集并初始化
int semid = create_sem(3);
//创建key值
key_t key = ftok("/",1314);
if(key == -1)
{
perror("ftok");
return -1;
}
//用key值创建一个共享内存,返回shmid
int shmid = shmget(key,PAGE_SIZE,IPC_CREAT|0666);
if(shmid == -1)
{
perror("shmget error");
return -1;
}
//映射共享内存到用户空间
char *addr = shmat(shmid,NULL,0);
if(addr == (void *)-1)
{
perror("shmat error");
return -1;
}
//使用共享内存
int count = 5;
while(count -- )
{
//p操作申请1号灯
P(semid,1);
//打印数据B
printf("%s\n",addr);
strcpy(addr,"C");
//v操作释放2号灯
V(semid,2);
}
//取消共享内存映射
if(shmdt(addr) == -1)
{
perror("shmdt error");
return -1;
}
return 0;
}
C.c
#include<my_head.h>
#define PAGE_SIZE 4096
#include "head.h"
int main(int argc, const char *argv[])
{
//创建信号灯集并初始化
int semid = create_sem(3);
//创建key值
key_t key = ftok("/",1314);
if(key == -1)
{
perror("ftok");
return -1;
}
//用key值创建一个共享内存,返回shmid
int shmid = shmget(key,PAGE_SIZE,IPC_CREAT|0666);
if(shmid == -1)
{
perror("shmget error");
return -1;
}
//映射共享内存到用户空间
char *addr = shmat(shmid,NULL,0);
if(addr == (void *)-1)
{
perror("shmat error");
return -1;
}
//使用共享内存
int count = 5;
while(count -- )
{
//p操作申请2号灯
P(semid,2);
//打印数据C
printf("%s\n",addr);
//存放数据B
strcpy(addr,"C");
//v操作释放0号灯
V(semid,0);
}
//取消共享内存映射
if(shmdt(addr) == -1)
{
perror("shmdt error");
return -1;
}
//删除共享内存
if(shmctl(shmid,IPC_RMID,NULL) == -1)
{
perror("shmctl error");
return -1;
}
//删除信号灯集
delete_sem(semid);
return 0;
}