程序代码:
sem.h:
1 #ifndef __SEM_H__
2 #define __SEM_H__
3
4 //创建信号灯集并初始化,semcount表示灯个数
5 int open_sem(int semcount);
6
7 //申请资源操作,semno表示灯的编号
8 int P(int semid,int semno);
9
10 //释放资源操作,semno表示灯的编号
11 int V(int semid,int semno);
12
13 //删除信号灯集
14 int del_sem(int semid);
15
16 #endif
~
sem.c:
1 #include<myhead.h>
2 union semun
3 {
4 int val;
5 struct semid_ds *buf;
6 unsigned short *array;
7 struct seminfo *__buf;
8 };
9 //定义给信号灯集中的指定信号灯赋值
10 int init_semno(int semid,int semno)
11 {
12 union semun buf;
13 printf("请输入要给编号为%d的灯设置的值:",semno);
14 scanf("%d",&buf.val);
15 //调用控制函数
16 if(semctl(semid,semno,SETVAL,buf)==-1)
17 {
18 perror("semctl error");
19 return -1;
20 }
21 return 0;
22 }
23 //创建或打开共享内存,参数为要申请的信号灯集中包含的灯的个数,返回值信号灯集的id
24 int open_sem(int semcount)
25 {
26 //创建key值
27 key_t key=-1;
28 if((key=ftok("/",'s'))==-1)
29 {
30 perror("ftok error");
31 return -1;
32 }
33 //通过key值创建一个信号灯集
34 int semid=-1;
35 if((semid=semget(key,semcount,IPC_CREAT|IPC_EXCL|0664))==-1)
36 {
37 //对错误码判断,EEXIST,说明信号灯集已存在
38 if(errno==EEXIST)
39 {
40 //直接打开信号灯集即可
41 semid=semget(key,semcount,IPC_CREAT|0664);
42 return semid;
43 }
44 perror("semget error");
45 return -1;
46 }
47 //给信号灯集的每个灯进行初始化操作
48 for(int i=0;i<semcount;i++)
49 {
50 //对编号为i的灯进行初始化
51 init_semno(semid,i);
52 }
53 return semid;
54 }
55 //进行申请资源操作,参数要申请的信号灯id,以及灯的编号
56 int P(int semid,int semno)
57 {
58 //定义要执行操作的结构体变量
59 struct sembuf buf;
60 buf.sem_num=semno;
61 buf.sem_op=-1;//申请资源
62 buf.sem_flg=0;//阻塞方式申请
63 //执行函数
64 if(semop(semid,&buf,1)==-1)
65 {
66 perror("P error");
67 return -1;
68 }
69 return 0;
70 }
71 //进行释放资源操作,参数为要申请的信号灯id,以及灯的编号
72 int V(int semid,int semno)
73 {
74 struct sembuf buf;
75 buf.sem_num=semno;
76 buf.sem_op=1;
77 buf.sem_flg=0;
78 if(semop(semid,&buf,1)==-1)
79 {
80 perror("V error");
81 return -1;
82 }
83 return 0;
84 }
85 //删除信号灯集的操作,参数为要删除的信号灯集
86 int del_sem(int semid)
87 {
88 //删除信号灯集
89 if(semctl(semid,0,IPC_RMID)==-1)
90 {
91 perror("delete error");
92 return -1;
93 }
94 return 0;
95 }
~
shmsnd.c:
1 #include<myhead.h>
2 #include "1.h"
3 #define PAGE_SIZE 4096
4 int main(int argc, const char *argv[])
5 {
6 //11.创建并初始化一个信号灯集
7 int semid=open_sem(2);
8 //1.创建key值
9 key_t key=-1;
10 if((key=ftok("/",'k'))==-1)
11 {
12 perror("ftok error");
13 return -1;
14 }
15 printf("key=%d\n",key);
16 //2.将物理内存创建出共享内存段
17 int shmid=-1;
18 if((shmid=shmget(key,PAGE_SIZE,IPC_CREAT|0664))==-1)
19 {
20 perror("shmget error");
21 return -1;
22 }
23 printf("shmid=%d\n",shmid);
24 //3.将共享内存段地址映射到用户空间
25 //NULL表示让系统自动选择页的分段
26 //0表示当前进程对共享内存具有读写功能
27 char *addr=(char *)shmat(shmid,NULL,0);
28 if(addr==(void*)-1)
29 {
30 perror("shmat error");
31 return -1;
32 }
33 printf("addr=%p\n",addr);
34 //4.操作共享内存
35 //char buf[128]="";
36 while(1)
37 {
38 //22.申请0号灯的资源
39 P(semid,0);
40 printf("请输入>>>");
41 fgets(addr,PAGE_SIZE,stdin);//从终端输入数据
42 addr[strlen(addr)-1]='\0';//将换行换成'\0'
43 printf("发送成功\n");
44 //33.释放1号灯的资源
45 V(semid,1);
46 if(strcmp(addr,"quit")==0)
47 break;
48 }
49 //5.取消映射
50 if(shmdt(addr)==-1)
51 {
52 perror("shmdt error");
53 return -1;
54 }
55 //6.删除共享内存
56 if(shmctl(shmid,IPC_RMID,NULL)==-1)
57 {
58 perror("shmctl error");
59 return -1;
60 }
61 return 0;
62 }
~
shmrcv:
1 #include<myhead.h>
2 #include"1.h"
3 #define PAGE_SIZE 4096
4 int main(int argc, const char *argv[])
5 {
6 //11.创建信号灯集
7 int semid=open_sem(2);
8 //1.创建key值
9 key_t key=-1;
10 if((key=ftok("/",'k'))==-1)
11 {
12 perror("ftok error");
13 return -1;
14 }
15 printf("key=%d\n",key);
16 //2.将物理内存创建共享内存段
17 int shmid=-1;
18 if((shmid=shmget(key,PAGE_SIZE,IPC_CREAT|0664))==-1)
19 {
20 perror("shmget error");
21 return -1;
22 }
23 printf("shmid=%d\n",shmid);
24 //3.将共享内存段地址映射到用户空间
25 //NULL表示让系统自动选择页分段
26 //0表示当前进程对共享内存的读写功能
27 char *addr=(char*)shmat(shmid,NULL,0);
28 if(addr==(void*)-1)
29 {
30 perror("shmat error");
31 return -1;
32 }
33 printf("addr=%p\n",addr);
34 //4.操作共享内存
35 //char buf[128]="";
36 while(1)
37 {
38 //22.申请1号灯的资源
39 P(semid,1);
40 printf("共享内存中的数据为:%s\n",addr);
41 if(strcmp(addr,"quit")==0)
42 break;
43 //33.释放0号灯的资源
44 V(semid,0);
45 }
46 //5.取消映射
47 if(shmdt(addr)==-1)
48 {
49 perror("shmdt error");
50 return -1;
51 }
52 //44.删除信号灯集
53 del_sem(semid);
54 return 0;
55 }
~
运行结果: