题目:使用信号灯实现三个进程分别实现abcabcabc
sem.h
#ifndef __SEM_H__
#define __SEM_H__
int init_sem(); //创建并初始化一个信号灯集
int P(int semid,int semnum); //申请senid信号灯集中的semnum号灯的资源
int V(int semid,int semnum); //释放semid信号灯集中的semnum号灯的资源
int sem_del(int semid); //删除信号灯集
#endif
zysem.h
#include <head.h>
union semun
{
int val;
struct semid_ds*buf;
unsigned short *array;
struct seminfo *__buf;
};
int init_semnum_value(int semid,int semnum,int value)
{
//为semctl准备第四个参数,是给信号灯设置值
union semun s;
s.val=value;
if(semctl(semid,semnum,SETVAL,s)==-1)
{
perror("semctl error");
return -1;
}
return 0;
}
int init_sem() //创建并初始化一个信号灯集
{
//创建key值
key_t key;
if((key=ftok("./",'k'))==-1)
{
perror("ftok error");
return -1;
}
//2创建信号灯集
int semid;
if((semid=semget(key,3,IPC_CREAT| IPC_EXCL | 0664))==-1)
{
//对错误码进行判断,如果错误码等于EEXIST
if(errno==EEXIST)
{
semid=semget(key,3,IPC_CREAT|0664);
}
else
{
perror("semget error");
return -1;
}
}
else
{
//3初始化信号灯
//调用自定义函数,为每个灯初始化
//参数1,要处理的信号灯集id
//参数2:要处理的信号灯编号
//参数3:给对应编号的灯初始值/当为1时不会堵塞
init_semnum_value(semid,0,1);
init_semnum_value(semid,1,0);
init_semnum_value(semid,2,0);
}
return semid; //将创建好的信号灯集id返回
}
//申请senid信号灯集中的semnum号灯的资源
int P(int semid,int semnum)
{
//定义设置灯信息的结构体的变量
struct sembuf buf;
buf.sem_num=semnum; //要处理的信号灯编号
buf.sem_op=-1; //表示申请资源
buf.sem_flg=0; //阻塞方式申请资源
//将semnum号灯的资源减1操作
if(semop(semid,&buf,1)==-1)
{
perror("p error");
return -1;
}
return 0;
}
int V(int semid,int semnum) //释放semid信号灯集中的semnum号灯的资源
{
//定义设置灯信息的结构体的变量
struct sembuf buf;
buf.sem_num=semnum; //要处理的信号灯编号
buf.sem_op=1; //表示申请资源
buf.sem_flg=0; //阻塞方式申请资源
//将semnum号灯的资源减1操作
if(semop(semid,&buf,1)==-1)
{
perror("v error");
return -1;
}
return 0;
}
int sem_del(int semid) //删除信号灯集
{
if(semctl(semid,0,IPC_RMID,0)==-1)
{
perror("semctl error");
return -1;
}
return 0;
}
a.c
#include <head.h>
#include "sem.h" //封装了信号灯集的函数头文件
#define SIZE 4096
int main(int argc, const char *argv[])
{
//一创建信号灯集并初始化
int semid;
if((semid=init_sem())==-1)
{
printf("创建信号灯集失败\n");
return -1;
}
//1获取key值
key_t key;
if((key=ftok("./",'s'))==-1)
{
perror("ftok error");
return -1;
}
//2创建共享内存
int shmid;
if((shmid=shmget(key,SIZE,IPC_CREAT|0664))==-1)
{
perror("shmget error");
return -1;
}
//3映射内存地址
char *addr=shmat(shmid,NULL,0);
if(addr==(void*)-1)
{
perror("shmat error");
return -1;
}
printf("addr=%p\n",addr);//输出共享内存的地址
//循环输入
for(int i=1;i<5;i++)
{//申请一号灯的资源
P(semid,2);
//向共享内存中写数据
printf("请输入>>");
*(char*)addr='a';//直接从终端获取数据到共享内存中
printf("%c\n",*((char*)addr));
addr[strlen(addr)-1]=0;
sleep(1);
//释放0号等资源(就是释放信号,0可以运行了)
V(semid,0);
if(strcmp(addr,"quit")==0)
{
break;
}
}
//4取消映射
if(shmdt(addr)==-1)
{
perror("shmdt error");
return -1;
}
//删除共享内存
//shmctl(shmid,IPC_RMID,NULL);
//四 删除信号灯集
//sem_del(semid);
return 0;
}
b.c
#include <head.h>
#include "sem.h" //封装了信号灯集的函数头文件
#define SIZE 4096
int main(int argc, const char *argv[])
{
//一创建信号灯集并初始化
int semid;
if((semid=init_sem())==-1)
{
printf("创建信号灯集失败\n");
return -1;
}
//1获取key值
key_t key;
if((key=ftok("./",'k'))==-1)
{
perror("ftok error");
return -1;
}
//2创建共享内存
int shmid;
if((shmid=shmget(key,SIZE,IPC_CREAT|0664))==-1)
{
perror("shmget error");
return -1;
}
//3映射内存地址
char *addr=shmat(shmid,NULL,0);
if(addr==(void*)-1)
{
perror("shmat error");
return -1;
}
printf("addr=%p\n",addr);//输出共享内存的地址
//循环输入
for(int i=1;i<5;i++)
{//申请一号灯的资源
P(semid,0);
//向共享内存中写数据
printf("请输入>>");
*(char*)addr='b';//直接从终端获取数据到共享内存中
printf("%c\n",*((char*)addr));
addr[strlen(addr)-1]=0;
sleep(1);
//释放0号等资源(就是释放信号,0可以运行了)
V(semid,1);
if(strcmp(addr,"quit")==0)
{
break;
}
}
//4取消映射
if(shmdt(addr)==-1)
{
perror("shmdt error");
return -1;
}
//删除共享内存
//shmctl(shmid,IPC_RMID,NULL);
//四 删除信号灯集
//sem_del(semid);
return 0;
}
c.c
#include <head.h>
#include "sem.h" //封装了信号灯集的函数头文件
#define SIZE 4096
int main(int argc, const char *argv[])
{
//一创建信号灯集并初始化
int semid;
if((semid=init_sem())==-1)
{
printf("创建信号灯集失败\n");
return -1;
}
//1获取key值
key_t key;
if((key=ftok("./",'k'))==-1)
{
perror("ftok error");
return -1;
}
//2创建共享内存
int shmid;
if((shmid=shmget(key,SIZE,IPC_CREAT|0664))==-1)
{
perror("shmget error");
return -1;
}
//3映射内存地址
char *addr=shmat(shmid,NULL,0);
if(addr==(void*)-1)
{
perror("shmat error");
return -1;
}
printf("addr=%p\n",addr);//输出共享内存的地址
//循环输入
for(int i=1;i<5;i++)
{//申请一号灯的资源
P(semid,1);
//向共享内存中写数据
printf("请输入>>");
*(char*)addr='c';//直接从终端获取数据到共享内存中
printf("%c\n",*((char*)addr));
addr[strlen(addr)-1]=0;
sleep(1);
//释放0号等资源(就是释放信号,0可以运行了)
V(semid,2);
if(strcmp(addr,"quit")==0)
{
break;
}
}
//4取消映射
if(shmdt(addr)==-1)
{
perror("shmdt error");
return -1;
}
//删除共享内存
//shmctl(shmid,IPC_RMID,NULL);
//四 删除信号灯集
//sem_del(semid);
return 0;
}