题目:使用信号灯实现三个进程分别实现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;
- }