#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_set_(int semid,int semno,int semval)
{
union semun us;
us.val=semval;
//调用semctl进行初始化
if(semctl(semid,semno,SETVAL,us)==-1)
{
perror("semctl error");
return -1;
}
return 0;
}
//创建信号灯集并初始化
int init_sem(int semnum)
{
key_t key;
if((key=ftok("/",'k'))==-1)
{
perror("ftok error");
return -1;
}
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;
}else
{
perror("semget error");
return -1;
}
}
for(int i=0;i<semnum;i++)
{
if(i==0)
{
sem_set_(semid,i,1);
}else
{
sem_set_(semid,i,0);
}
}
}
//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 del_sem(int semid)
{
if(semctl(semid,0,IPC_RMID,0)==-1)
{
perror("delete error");
return -1;
}
}
#include <myhead.h>
#include "sem.h"
int main(int argc, const char *argv[])
{
//创建信号灯集
int semid = init_sem(4);
//创建key值
key_t key;
if((key = ftok("/", 'k')) == -1)
{
perror("ftok error");
return -1;
}
//创建共享内存
int shmid;
if((shmid = shmget(key, 4096, IPC_CREAT|0664)) == -1)
{
perror("shmget error");
return -1;
}
//映射内存
char *addr = NULL;
if((addr = shmat(shmid, NULL, 0)) == (void*)-1)
{
perror("shmat error");
return -1;
}
//创建进程
pid_t pid;
pid = fork();
if(pid < 0)
{
perror("fork error");
return -1;
}else if(pid == 0)
{
//子进程
while(1)
{
//等待3号信号灯的资源
P(semid,3);
//读取共享内存中的数据
printf("读取的数据为%s\n",addr);
//释放2号信号灯的资源
V(semid,2);
if(strcmp(addr,"quit") == 0)
{
break;
}
}
//退出子进程
exit(EXIT_SUCCESS);
}else
{
//父进程
while(1)
{
//等待0号信号灯资源
P(semid,0);
//向共享内存中写入数据
fgets(addr,4096,stdin);
addr[strlen(addr)-1] = '\0';
//释放1号灯资源
V(semid,1);
//设定循环退出条件
if(strcmp(addr,"quit") == 0)
{
break;
}
}
//回收子进程资源
wait(NULL);
}
//取消映射
if(shmdt(addr) == -1)
{
perror("shmdt error");
return -1;
}
return 0;
}