include <myhead.h>
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
//信号灯集里每个信号灯的初始化
int sem_value(int semid,int semno,int semvalue)
{
union semun us;
us.val=semvalue;
if(semctl(semid,semno,SETVAL,us)==-1)
{
perror("semctr");
return -1;
}
return 0;
}
//创建信号灯集并初始化函数
int init_sem(int semnum)
{
//1.创建一个key钥匙
key_t key;
if((key=ftok("/",'t'))==-1)
{
perror("ftok");
return -1;
}
//2.创建一个信号灯集
int semid;
if((semid=semget(key,semnum,IPC_CREAT|IPC_EXCL|0664))==-1)
{
if(errno==EEXIST)
{
//防止多进程同时调用时多次初始化
semid=semget(key,semnum,IPC_CREAT|0664);
return semid;
}
perror("semget");
return -1;
}
//3.信号灯集初始化
for(int i=0;i<semnum;i++)
{
if(i==0)
{
//参数1:id
//参数2:初始化的信号灯编号
//参数3:初始化的信号灯的value值
sem_value(semid,i,1);
}
else
{
sem_value(semid,i,0);
}
}
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("semop");
return -1;
}
return 0;
}
//w操作函数
int W(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("semop");
return -1;
}
return 0;
}
//删除信号灯的函数
int del_sem(int semid)
{
if(semctl(semid,0,IPC_RMID,0)==-1)
{
perror("semctl");
return -1;
}
return 0;
}
#include <myhead.h>
#include "sem.h"
int main(int argc, const char *argv[])
{
//创建钥匙
key_t key=-1;
if((key=ftok("/",'c'))==-1)
{
perror("ftok");
return -1;
}
//创建共享享内存
int shmid;
if((shmid=shmget(key,4096,IPC_CREAT|0664))==-1)
{
perror("shmget");
return -1;
}
//映射到用户空间
char *adder;
if((adder=shmat(shmid,NULL,0))==(void *)-1)
{
perror("shmat");
return -1;
}
//创建一个信号灯集
int semid;
semid=init_sem(4);
//创建父子进程
pid_t pid;
pid=fork();
if(pid<0)
{
perror("fork");
return -1;
}
else if(pid>0)
{
//父进程
while(1)
{
//等待0信号资源
W(semid,0);
fgets(adder,4096,stdin);
adder[strlen(adder)-1]='\0';
//释放1信号资源
P(semid,1);
if(strcmp(adder,"quit")==0)
{
break;
}
}
wait(NULL);
}
else
{
//子进程
while(1)
{
//等待3信号资源
W(semid,3);
//房子里面拿东西
printf("共享内存数据:%s\n",adder);
//释放2信号资源
P(semid,2);
if(strcmp(adder,"quit")==0)
{
break;
}
}
exit(EXIT_SUCCESS);
}
//取消链接
shmdt(adder);
return 0;
}
#include <myhead.h>
#include "sem.h"
int main(int argc, const char *argv[])
{
//搞个小钥匙
key_t key=-1;
if((key=ftok("/",'c'))==-1)
{
perror("ftok");
return -1;
}
//搞个小房子
int shmid;
if((shmid=shmget(key,4096,IPC_CREAT|0664))==-1)
{
perror("shmget");
return -1;
}
//给被人地址
char *adder;
if((adder=shmat(shmid,NULL,0))==(void *)-1)
{
perror("shmat");
return -1;
}
//打开信号灯集
int semid;
semid=init_sem(4);
//创建父子进程
pid_t pid;
pid=fork();
if(pid<0)
{
perror("fork");
return -1;
}
else if(pid>0)
{
//父进程
while(1)
{
//等待1信号资源
W(semid,1);
//房子里面拿东西
printf("共享内存数据:%s\n",adder);
//释放0信号资源
P(semid,0);
if(strcmp(adder,"quit")==0)
{
break;
}
}
wait(NULL);
}
else
{
//子进程
while(1)
{
//等待2信号资源
P(semid,2);
W(semid,2);
fgets(adder,4096,stdin);
adder[strlen(adder)-1]='\0';
//释放3信号资源
P(semid,3);
if(strcmp(adder,"quit")==0)
{
break;
}
}
exit(EXIT_SUCCESS);
}
//让别人忘记地址
shmdt(adder);
//龙卷风摧毁停车场,拆房子
if(shmctl(shmid,IPC_RMID,NULL)==-1)
{
perror("shmctl");
return -1;
}
//删除信号灯集
del_sem(semid);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/2e9449d1dcef715782f1f40d746910fb.png)