1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/ipc.h>
4 #include <sys/shm.h>
5 #include <errno.h>
6 #include <sys/sem.h>
7 #include <string.h>
8
9 #define N 128
10 struct shmbuf{
11 char buf[N];
12 };
13 union semun{
14 int val;
15 };
16 int main(int argc, const char *argv[])
17 {
18 key_t key;
19
20 if((key = ftok(".", 'q')) < 0){
21 perror("ftok error");
22 return -1;
23 }
24
25 int shmid;
26 struct shmbuf *shm;
27 if((shmid = shmget(key, 512, IPC_CREAT|IPC_EXCL|0664)) < 0){
28 if(errno != EEXIST){
29 perror("shmget error");
30 return -1;
31 }
32 else{
33 shmid = shmget(key, 512, 0664);
34 }
35 }
36
37 if((shm = shmat(shmid, NULL, 0)) > 0){
38 printf("shm:%p\n", shm);
39 }
40
41 int semid;
42 union semun semun;
43
44 struct sembuf sem;
45 semid = semget(key, 2, IPC_CREAT|IPC_EXCL|0664);
46
47 if(semid < 0){
48 if(errno != EEXIST){
49 perror("semget error");
50 return -1;
51 }
52 else{
53 semid = semget(key, 2, 0664);
54 }
55 }
56 else{
57 /*初始化信号量的值*/
58 semun.val = 0;
59 semctl(semid, 0, SETVAL, semun);
60 semun.val = 1;
61 semctl(semid, 1, SETVAL, semun);
62 }
63
64 while(1){
65 /*申请写操作信号量*/
66 sem.sem_num = 1;
67 sem.sem_op = -1;
68 sem.sem_flg = 0;
69 semop(semid, &sem, 1);
70
71 fgets(shm->buf, N, stdin);
72 shm->buf[strlen(shm->buf) - 1] = '\0';
73
74
75 /*释放读操作信号量*/
76 sem.sem_num = 0;
77 sem.sem_op = 1;
78 sem.sem_flg = 0;
79 semop(semid, &sem, 1);
80
81 if(strncmp(shm->buf, "quit", 4) == 0){
82 goto ERR;
83 }
84 }
85 return 0;
86 ERR:
87 shmdt(shm);
88 }
读共享内存的代码如下,程序不退出,可以持续读取。
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/ipc.h>
4 #include <sys/shm.h>
5 #include <errno.h>
6 #include <sys/sem.h>
7 #include <string.h>
8
9 #define N 128
10 struct shmbuf{
11 char buf[N];
12 };
13 union semun{
14 int val;
15 };
16 int main(int argc, const char *argv[])
17 {
18 key_t key;
19
20 if((key = ftok(".", 'q')) < 0){
21 perror("ftok error");
22 return -1;
23 }
24
25 int shmid;
26 struct shmbuf *shm;
27 /*创建并打开共享内存*/
28 if((shmid = shmget(key, 512, IPC_CREAT|IPC_EXCL|0664)) < 0){
29 if(errno != EEXIST){
30 perror("shmget error");
31 return -1;
32 }
33 else{
34 /*如果共享内存已存在,则打开*/
35 shmid = shmget(key, 512, 0664);
36 }
37 }
38
39 /*建立映射*/
40 if((shm = shmat(shmid, NULL, 0)) > 0){
41 printf("shm:%p\n", shm);
42 }
43
44 int semid;
45 union semun semun;
46
47 struct sembuf sem;
48 /*创建并打开信号量集合*/
49 semid = semget(key, 2, IPC_CREAT|IPC_EXCL|0664);
50
51 if(semid < 0){
52 if(errno != EEXIST){
53 perror("semget error");
54 return -1;
55 }
56 else{
57 /*如果信号量集存在,则打开*/
58 semid = semget(key, 2, 0664);
59 }
60 }
61 else{
62 /*初始化信号量的值
63 *将编号为0的信号量定义为读操作信号量
64 *读操作信号量初始化值为0
65 */
66 semun.val = 0;
67 semctl(semid, 0, SETVAL, semun);
68 /*将编号为1的信号量定义为写操作信号量
69 *写操作信号量初始值为1
70 */
71 semun.val = 1;
72 semctl(semid, 1, SETVAL, semun);
73 }
74
75 while(1){
76 //申请读操作信号量
77 sem.sem_num = 0;
78 sem.sem_op = -1;
79 sem.sem_flg = 0;
80 semop(semid, &sem, 1);
81
82 if(strncmp(shm->buf, "quit", 4) == 0){
83 goto ERR;
84 }
85 printf("buf:%s\n", shm->buf);
86
87 //释放写操作信号量
88 sem.sem_num = 1;
89 sem.sem_op = 1;
90 sem.sem_flg = 0;
91 semop(semid, &sem, 1);
92 }
93 return 0;
94 ERR:
95 shmdt(shm);
96 shmctl(shmid, IPC_RMID, NULL);
97 semctl(semid, 0, IPC_RMID, NULL);
98 semctl(semid, 1, IPC_RMID, NULL);
99 }
运行结果如下,从终端输入,另外一个进程则读取数据并输出,当输入“quit”时,程序全部退出,且删除一切资源。
linux@Master:~/1000phone/sem$ ./write
shm:0x7ffcee3df000
hello
world
quit
执行读操作程序。
linux@Master:~/1000phone/sem$ ./read
shm:0x7f20ccdb4000
buf:hello
buf:world