使用三个程序来完成输出 ABCABCABCABCABC
1 #include <head.h>
2 #include "sem.h"
3 int main(int argc, const char *argv[])
4 {
5 //1.创建信号灯集
6 int semid=create_sem(3);//因为有3个进程,所以有3个灯
7 if (semid==-1)
8 {
9 perror("semid error1");
10 return -1;
11 }
12 //system("fg 1");
13 getchar();
14 int n=5;//输5次
15 while(n--)
16 {
17 P(semid,2);//2.申请2号信号灯资源
18 printf("A");
19 fflush(stdout);
20 V(semid,0);//3.释放0号信号灯资源
21 }
22 return 0;
23 }
~
1 #include <head.h>
2 #include "sem.h"
3 int main(int argc, const char *argv[])
4 {
5 //1.打开信号灯集
6 int semid=create_sem(3);//因为有3个进程,所以有3个灯
7 int n=5;//输5次
8 while(n--)
9 {
10 P(semid,0);//2.申请2号信号灯资源
11 printf("B");
12 fflush(stdout);
13 V(semid,1);//3.释放0号信号灯资源
14 }
15 return 0;
16 }
~
~
1 #include <head.h>
2 #include "sem.h"
3 int main(int argc, const char *argv[])
4 {
5 //1.打开信号灯集
6 int semid=create_sem(3);//因为有3个进程,所以有3个灯
7 int n=5;//输5次
8 while(n--)
9 {
10 P(semid,1);//2.申请2号信号灯资源
11 printf("C");
12 fflush(stdout);
13 V(semid,2);//3.释放0号信号灯资源
14 }
15 //4.删除信号灯集
16 del_sem(semid);
17 return 0;
18 }
~
将共享内存和信号灯集完成两个进程间通信程序重新实现一下
shmsnd.c
1 #include <head.h>
2 #define PAGE_SIZE 4096
3 int main(int argc, const char *argv[])
4 {
5 //创建key值
6 key_t key=ftok("/",'k');
7 if (key==-1)
8 {
9 perror("key error");
10 return -1;
11 }
12 printf("key=%#x\n",key);
13 //通过key值创建共享内存段
14 int shmid=shmget(key,PAGE_SIZE,IPC_CREAT|0664);
15 if (shmid==-1)
16 {
17 perror("shmget error");
18 return -1;
19 }
20 printf("shmid=%d\n",shmid);
21 //将共享内存段映射到用户空间
22 char *addr=(char*)shmat(shmid,NULL,0);
23 if (addr==(void*)-1)
24 {
25 perror("shmat error");
26 return -1;
27
28 }
29 printf("addr=%p\n",addr);//输出虚拟地址
30
31 //使用共享内存段
32 while (1)
33 {
34 printf("请输入>>>");
35 fgets(addr,PAGE_SIZE,stdin);
36 addr[strlen(addr)-1]='\0';
37
38 //判断退出条件
39 if (strcmp(addr,"quit")==0)
40 {
41 break;
42 }
43 }
44 //取消映射
45 if (shmdt(addr)==-1)
46 {
47 perror("shmdt error");
48 return -1;
49 }
50 //删除共享内存,已经在rcv文件中删除,这里不再进行删除操作
51 return 0;
52 }
~
~
~
shmrcv.c
1 #include <head.h>
2 #define PAGE_SIZE 4096
3 int main(int argc, const char *argv[])
4 {
5 //创建key值
6 key_t key=ftok("/",'k');
7 if (key==-1)
8 {
9 perror("key error");
10 return -1;
11 }
12 printf("key=%#x\n",key);
13 //通过key值创建共享内存段
14 int shmid=shmget(key,PAGE_SIZE,IPC_CREAT|0664);
15 if (shmid==-1)
16 {
17 perror("shmget error");
18 return -1;
19 }
20 printf("shmid=%d\n",shmid);
21 //将共享内存段映射到用户空间
22 char *addr=(char*)shmat(shmid,NULL,0);
23 if (addr==(void*)-1)
24 {
25 perror("shmat error");
26 return -1;
27
28 }
29 printf("addr=%p\n",addr);//输出虚拟地址
30 char cmp[PAGE_SIZE];
31 //使用共享内存段
32 while (1)
33 {
34 if (strcmp(cmp,addr) != 0)
35 {
36 strcpy(cmp,addr);
37 printf("共享内存中的数据为:%s\n",addr);
38 }
39 //获取共享内存中的数据
40 //判断退出条件
41 if (strcmp(addr,"quit")==0)
42 {
43 break;
44 }
45 }
46 //取消映射
47 if (shmdt(addr)==-1)
48 {
49 perror("shmdt error");
50 return -1;
51 }
52 //删除共享内存
53 if(shmctl(shmid,IPC_RMID,NULL)==-1)
54 {
55 perror("shmctl error");
56 return -1;
57 }
58 return 0;
59 }
~
~
3.信号灯集
sem.c
1 #include <head.h>
2 //共用体类型
3 union semun {
4 int val; /* Value for SETVAL */
5 struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
6 unsigned short *array; /* Array for GETALL, SETALL */
7 struct seminfo *__buf; /* Buffer for IPC_INFO
8 (Linux-specific) */
9 };
10 //单个信号灯初始化函数
11 int init_sem(int semid,int semno)
12 {
13 int val=-1;
14 printf("请输入%d号灯的初始值",semno);
15 scanf("%d",&val);
16 getchar();
17 union semun us;
18 us.val=val;
19 if(semctl(semid, semno, SETVAL, us) == -1)
20 {
21 perror("set val error");
22 return -1;
23 }
24
25 //成功返回0
26 return 0;
27
28 }
29
30 //信号灯集的申请,初始化信号灯,并返回信号灯集的id
31 int create_sem(int semcount)//semnum信号灯的个数
32 {
33 //创建key值
34 key_t key=ftok("/",'k');
35 if (key==-1)
36 {
37 perror("ftok error");
38 return -1;
39 }
40 //通过key值申请信号灯集
41 int semid=semget(key,semcount,IPC_CREAT|IPC_EXCL|0664);
42 if (semid==-1)
43 {
44 if (errno==EEXIST)
45 {
46 semid=semget(key,semcount,IPC_CREAT);
47 return semid;
48
49 }
50 perror("semget error");
51 return -1;
52 }
53 //给信号灯集中的所有信号灯初始化
54 for (int i=0;i<semcount ;i++)
55 {
56 init_sem(semid,i);
57 }
58 return semid;
59
60 }
61 //申请信号灯资源操作(p操作:是减一操作)
62 int P(int semid,int semno)//semno//信号灯的编号
63 {
64 //定义一个操作的结构体变量
65 struct sembuf buf;
66 buf.sem_num = semno; //要操作的灯的编号
67 buf.sem_op = -1; //表示申请资源操作
68 buf.sem_flg = 0; //如果没有资源,则阻塞等待
69
70 //调用semop函数完成P操作
71 if(semop(semid, &buf, 1) == -1)
72 {
73 perror("P error");
74 return -1;
75 }
76
77 return 0; //成功返回0
78
79 }
80 //释放信号灯资源操作(v操作:加一操作)
81 int V(int semid,int semno)
82 {
83 //定义一个操作的结构体变量
84 struct sembuf buf;
85 buf.sem_num = semno; //要操作的灯的编号
86 buf.sem_op = 1; //表示释放资源操作
87 buf.sem_flg = 0; //如果没有资源,则阻塞等待
88
89 //调用semop函数完成v操作
90 if(semop(semid, &buf, 1) == -1)
91 {
92 perror("v error");
93 return -1;
94 }
95
96 return 0; //成功返回0
97
98 }
99 //信号灯集的删除
100 int del_sem(int semid)
101 {
102 if (semctl(semid,0,IPC_RMID,0)==-1)
103 {
104 perror("IPC_RMID error");
105 return -1;
106 }
107 return 0;
108
109
110 }
~
~
~
sem.h
1 #ifndef _SEM_H__
2 #define _SEM_H__
3 //信号灯集的申请,初始化信号灯,并返回信号灯集的id
4 int create_sem(int semcount);//semnum信号灯的个数
5 //申请信号灯资源操作(p操作:是减一操作)
6 int P(int semid,int semno);//semno//信号灯的编号
7 //释放信号灯资源操作(v操作:加一操作)
8 int V(int semid,int semno);
9 //信号灯集的删除
10 int del_sem(int semid);
11 #endif
~
~
01shemsnd.c
1 #include <head.h>
2 #include "sem.h"
3 #define PAGE_SIZE 4096
4 int main(int argc, const char *argv[])
5 {
6 //1.创建一个信号灯集
7 int semid=create_sem(2);
8 //创建key值
9 key_t key=ftok("/",'k');
10 if (key==-1)
11 {
12 perror("key error");
13 return -1;
14 }
15 printf("key=%#x\n",key);
16 //通过key值创建共享内存段
17 int shmid=shmget(key,PAGE_SIZE,IPC_CREAT|0664);
18 if (shmid==-1)
19 {
20 perror("shmget error");
21 return -1;
22 }
23 printf("shmid=%d\n",shmid);
24 //将共享内存段映射到用户空间
25 char *addr=(char*)shmat(shmid,NULL,0);
26 if (addr==(void*)-1)
27 {
28 perror("shmat error");
29 return -1;
30
31 }
32 printf("addr=%p\n",addr);//输出虚拟地址
33
34 //使用共享内存段
35 while (1)
36 {
37 //2.申请信号资源
38 P(semid,1);
39 printf("请输入>>>");
40 fgets(addr,PAGE_SIZE,stdin);
41 addr[strlen(addr)-1]='\0';
42 //3.释放信号资源
43 V(semid,0);
44
45 //判断退出条件
46 if (strcmp(addr,"quit")==0)
47 {
48 break;
49 }
50 }
51 //取消映射
52 if (shmdt(addr)==-1)
53 {
54 perror("shmdt error");
55 return -1;
56 }
57 //删除共享内存,已经在rcv文件中删除,这里不再进行删除操作
58 return 0;
59 }
~
~
~
~
~
02shemrcv.c
1 #include <head.h>
2 #include "sem.h"
3 #define PAGE_SIZE 4096
4 int main(int argc, const char *argv[])
5 {
6 //1.打开一个信号灯集
7 int semid=create_sem(2);
8 if (semid==-1)
9 {
10 perror("semid error");
11 return -1;
12
13 }
14 //创建key值
15 key_t key=ftok("/",'k');
16 if (key==-1)
17 {
18 perror("key error");
19 return -1;
20 }
21 printf("key=%#x\n",key);
22 //通过key值创建共享内存段
23 int shmid=shmget(key,PAGE_SIZE,IPC_CREAT|0664);
24 if (shmid==-1)
25 {
26 perror("shmget error");
27 return -1;
28 }
29 printf("shmid=%d\n",shmid);
30 //将共享内存段映射到用户空间
31 char *addr=(char*)shmat(shmid,NULL,0);
32 if (addr==(void*)-1)
33 {
34 perror("shmat error");
35 return -1;
36
37 }
38 printf("addr=%p\n",addr);//输出虚拟地址
39 //使用共享内存段
40 while (1)
41 {
42 //2.申请信号资源
43 P(semid,0);
44 printf("共享内存中的数据为:%s\n",addr);
45 //3.释放信号资源
46 V(semid,1);
47 //获取共享内存中的数据
48 //判断退出条件
49 if (strcmp(addr,"quit")==0)
50 {
51 break;
52 }
53 }
54 //取消映射
55 if (shmdt(addr)==-1)
56 {
57 perror("shmdt error");
58 return -1;
59 }
60 //删除共享内存
61 if(shmctl(shmid,IPC_RMID,NULL)==-1)
62 {
63 perror("shmctl error");
64 return -1;
65 }
66 //删除信号灯集
67 del_sem(semid);
68 return 0;
69 }
~
~
~
1.左值右值的区别:
2.如果两个指针同时指向一片地址,如果一个指针释放掉,另一个指针怎么知道已经释放了?