
- #ifndef __SEM
- 2 #define __SEM
- 3
- 4 //声明一个创>
- 5 int init_sem(
- 6
- 7 //声明一个p操
- 8 int P(int sem
- 9
- 10 //声明一个v操
- 11 int W(int sem
- 12
- 13 //声明一个删>
- 14 int del_sem(i
- 15
- 16 #endif
- 1 #include
- 2 union semun {
- 3 int val; /* Value for SETVAL */
- 4 struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
- 5 unsigned short *array; /* Array for GETALL, SETALL */
- 6 struct seminfo *__buf; /* Buffer for IPC_INFO
- 7 (Linux-specific) */
- 8 };
- 9 //信号灯集里每个信号灯的初始化
- 10 int sem_value(int semid,int semno,int semvalue)
- 11 {
- 12 union semun us;
- 13 us.val=semvalue;
- 14 if(semctl(semid,semno,SETVAL,us)==-1)
- 15 {
- 16 perror("semctr");
- 17 return -1;
- 18 }
- 19 return 0;
- 20 }
- 21 //创建信号灯集并初始化函数
- 22 int init_sem(int semnum)
- 23 {
- 24 //1.创建一个key钥匙
- 25 key_t key;
- 26 if((key=ftok("/",'t'))==-1)
- 27 {
- 28 perror("ftok");
- 29 return -1;
- 30 }
- 31 //2.创建一个信号灯集
- 32 int semid;
- 33 if((semid=semget(key,semnum,IPC_CREAT|IPC_EXCL|0664))==-1)
- 34 {
- 35 if(errno==EEXIST)
- 36 {
- 37 //防止多进程同时调用时多次初始化
- 38 semid=semget(key,semnum,IPC_CREAT|0664);
- 39 return semid;
- 40 }
- 41 perror("semget");
- 42 return -1;
- 43 }
- 44 //3.信号灯集初始化
- 45 for(int i=0;i
- 46 {
- 47 if(i==0)
- 48 {
- 49 //参数1:id
- 50 //参数2:初始化的信号灯编号
- 51 //参数3:初始化的信号灯的value值
- 52 sem_value(semid,i,1);
- 53 }
- 54 else
- 55 {
- 56 sem_value(semid,i,0);
- 57 }
- 58 }
- 59 return semid;
- 60 }
- 61
- 62 //p操作函数
- 63 int P(int semid,int semno)
- 64 {
- 65 struct sembuf buf;
- 66 buf.sem_num=semno;//灯集里灯编号
- 67 buf.sem_op=1; //释放资源
- 68 buf.sem_flg=0; //阻塞
- 69 if(semop(semid,&buf,1)==-1)
- 70 {
- 71 perror("semop");
- 72 return -1;
- 73 }
- 74 return 0;
- 75
- 76 }
- 77 //w操作函数
- 78 int W(int semid,int semno)
- 79 {
- 80 struct sembuf buf;
- 81 buf.sem_num=semno;//灯集里灯编号
- 82 buf.sem_op=-1; //申请资源
- 83 buf.sem_flg=0; //阻塞
- 84 if(semop(semid,&buf,1)==-1)
- 85 {
- 86 perror("semop");
- 87 return -1;
- 88 }
- 89 return 0;
- 90 }
- 91
- 92 //删除信号灯的函数
- 93 int del_sem(int semid)
- 94 {
- 95 if(semctl(semid,0,IPC_RMID,0)==-1)
- 96 {
- 97 perror("semctl");
- 98 return -1;
- 99 }
- 100 return 0;
- 101 }
- 1 #include
- 2 #include "sem.h"
- 3 int main(int argc, const char *argv[])
- 4 {
- 5 //创建钥匙
- 6 key_t key=-1;
- 7 if((key=ftok("/",'c'))==-1)
- 8 {
- 9 perror("ftok");
- 10 return -1;
- 11 }
- 12 //创建共享享内存
- 13 int shmid;
- 14 if((shmid=shmget(key,4096,IPC_CREAT|0664))=
- 15 {
- 16 perror("shmget");
- 17 return -1;
- 18 }
- 19 //映射到用户空间
- 20 char *adder;
- 21 if((adder=shmat(shmid,NULL,0))==(void *)-1)
- 22 {
- 23 perror("shmat");
- 24 return -1;
- 25 }
- 26 //创建一个信号灯集
- 27 int semid;
- 28 semid=init_sem(4);
- 29 //创建父子进程
- 30 pid_t pid;
- 31 pid=fork();
- 32 if(pid<0)
- 33 {
- 34 perror("fork");
- 35 return -1;
- 36 }
- 37 else if(pid>0)
- 38 {
- 39 //父进程
- 40 while(1)
- 41 {
- 42 //等待0信号资源
- 43 W(semid,0);
- 44 fgets(adder,4096,stdin);
- 45 adder[strlen(adder)-1]='\0';
- 46 //释放1信号资源
- 47 P(semid,1);
- 48 if(strcmp(adder,"quit")==0)
- 49 {
- 50 break;
- 51 }
- 52 }
- 53 wait(NULL);
- 54 }
- 55 else
- 56 {
- 57 //子进程
- 58 while(1)
- 59 {
- 60 //等待3信号资源
- 61 W(semid,3);
- 62 //房子里面拿东西
- 63 printf("共享内存数据:%s\n",adder);
- 64 //释放2信号资源
- 65 P(semid,2);
- 66 if(strcmp(adder,"quit")==0)
- 67 {
- 68 break;
- 69 }
- 70 }
- 71 exit(EXIT_SUCCESS);
- 72 }
- 73 //取消链接
- 74 shmdt(adder);
- 75 return 0;
- 76 }
