共享内存

共享内存

共享内存是一种最为高效的进程间通信方式。因为进程可以直接读写内存,不需要任何数据的复制。为了在多个进程间交换信息,内核专门留出了一块内存区。这段内存区可以由需要访问的进程将其映射到自己的私有地址空间。因此,进程就可以直接读写这一块内存区而不需要要进行数据的复制,从而大大提高了效率。

共享内存使用

函数说明

共享内存的实现分为两个步骤:

  • 第一步是创建共享内存,这里用到的函数是shmget(),也就是从内存中获取一段共享内存区域
  • 第二步映射共享内存,也就是把这段创建的共享内存映射到具体的进程空间中,这里使用的函数是shmat()
  • 最后还有一个撤销映射的函数,shmdt()

函数格式

1
2
3
4
5
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int shmget (key_t key, int size, int shmflg);
C

key:共享内存的键值,多个进程可以通过它访问同一个共享内存,IPC_PRIVATE用于创建当前进程的私有共享内存

size:共享内存的大小

shmflg:同open()函数的权限位,也可以使用八进制表示法

成功返回共享内存段标识符,出错返回-1

1
2
3
4
5
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

char *shmat (int shmid, const void *shmaddr, int shmflg);
C

shmid:要映射的共享内存区标识符

shmaddr:将共享内存映射到指定地址(0表示系统自动分配)

shmflg:默认0可读可写,SHM_RDONLY只读

成功返回被映射的段地址,出错返回-1

1
2
3
4
5
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int shmdt (const void *shmaddr);
C

shmaddr:被映射的共享内存段地址

成功返回0,出错返回-1

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define BUFFER_SIZE 2048

int main ()
{
pid_t pid;
int shmid;
char *shm_addr;
char flag[] = "WROTE";
char buff[BUFFER_SIZE] = {0};

if ((shmid = shmget (IPC_PRIVATE, BUFFER_SIZE, 0666)) < 0)
{
perror ("shmget");
exit (1);
}
else
{
printf ("Creat shared-memory: %d\n", shmid);
}

system ("ipcs -m");

pid = fork ();

if (pid == -1)
{
perror ("fork");
exit (1);
}
else if (pid == 0)
{
if ( (shm_addr = shmat (shmid, 0, 0)) == (void*) -1)
{
perror ("Child: shmat");
exit (1);
}
else
{
printf ("Child: Attach shared-memory: %p\n", shm_addr);
}
system ("ipcs -m");

while (strncmp (shm_addr, flag, strlen (flag)))
{
printf ("Child: Wait for enable data...\n");
sleep (5);
}

strcpy (buff, shm_addr + strlen (flag));
printf ("Child: Shared-memory : %s\n", buff);

if ((shmdt (shm_addr)) < 0)
{
perror ("Child: shmdt");
exit(1);
}
else
{
printf ("Child: Deattach shared-memory\n");
}
system ("ipcs -m");
}
else
{
if ( (shm_addr = shmat (shmid, 0, 0)) == (void*) -1)
{
perror ("Parent: shmat");
exit (1);
}
else
{
printf ("Parent: Attach shared-memory: %p\n", shm_addr);
}
sleep (1);
printf ("\nInput some string:\n");
fgets (buff, BUFFER_SIZE, stdin);
strncpy (shm_addr + strlen (flag), buff, strlen (buff));
strncpy (shm_addr, flag, strlen (flag));

if ((shmdt (shm_addr)) < 0)
{
perror ("Parent: shmdt");
exit(1);
}
else
{
printf ("Parent: Deattach shared-memory\n");
}
system ("ipcs -m");

waitpid(pid, NULL, 0);

if (shmctl (shmid, IPC_RMID, NULL) == -1)
{
perror ("shmctl");
exit(1);
}
else
{
printf ("Delete shared-memory\n");
}
system ("ipcs -m");

printf ("Finished\n");
}

exit (0);
}

C

共享内存
https://carl-5535.github.io/2021/05/31/Linux系统编程/共享内存/
作者
Carl Chen
发布于
2021年5月31日
许可协议