进程间通信之共享内存
felicx 化神

定义

内核管理一片物理内存,允许不同的进程同时映射,多个进程可以映射同一块内存,被多个进程同时映射的物理内存,即共享内存。
映射物理内存叫挂接,用完以后解除映射叫脱接。
共享内存的特点:

  • 优点:最快的IPC
  • 缺点:要编程者自己实现对共享内存互斥访问

实现

编程模型:具体函数的用法可以用man手册(强力推荐)

写入内存进程

  • 获得key, ftok()
  • 使用key来创建一个共享内存 shmget()
  • 映射共享内存(得到虚拟地址), shmat()
  • 使用共享内存, 往共享内存中写入数据
  • 解除映射 shmdt()
  • 如果共享内存不再使用,可以使用shmctl()销毁共享内存

从内存读取进程

  • 获得key, ftok()
  • 使用key来获得一个共享内存 shmget()
  • 映射共享内存(得到虚拟地址), shmat()
  • 使用共享内存, 读取共享内存中的数据
  • 解除映射 shmdt()

代码如下:

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
// write_memory.cc
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/time.h>
#include <unistd.h>
#include <ctime>
#include <iostream>
#include "./shmdata.h"

int main() {
int running = 1;
void *shm = NULL;
struct shared_use_st *shared = NULL;
int shmid;

// 创建共享内存
shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT);
if (shmid == -1) {
fprintf(stderr, "shmget failed\n");
exit(EXIT_FAILURE);
}

// 将共享内存连接到当前进程的地址空间
shm = shmat(shmid, (void *)0, 0);
if (shm == (void *)-1) {
fprintf(stderr, "shmat err\n");
exit(EXIT_FAILURE);
}

shared = (struct shared_use_st *)shm;
while (running) {
struct timeval tv;
gettimeofday(&tv, NULL);
std::string time_ = std::to_string(1000 * tv.tv_sec + tv.tv_usec / 1000);
// std::string time_ = std::to_string(1000 * tv.tv_sec);
strcpy(shared->timestamp, time_.c_str());
std::cout << "You wrote: " << shared->timestamp << std::endl;
usleep(1000);

shared->written = 1;
}
if (shmdt(shm) == -1) {
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}


// read_memory.cc
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
#include <unistd.h>
#include <iostream>
#include "./shmdata.h"

int main() {
int running = 1;
void *shm = NULL;
struct shared_use_st *shared;
int shmid;

// 创建共享内存
shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT);
if (shmid == -1) {
fprintf(stderr, "shmget err\n");
exit(EXIT_FAILURE);
}

// 将共享内存连接到当前进程的地址空间
shm = shmat(shmid, 0, 0);
if (shm == (void *)-1) {
fprintf(stderr, "shmat err\n");
exit(EXIT_FAILURE);
}
shared = (struct shared_use_st *)shm;
shared->written = 0;
while (running) {
if (shared->written != 0) {
std::cout << "You receivr: " << shared->timestamp << std::endl;
shared->written = 0;
}
usleep(5000);
}

if (shmdt(shm) == -1) {
fprintf(stderr, "shmdt err\n");
exit(EXIT_FAILURE);
}

if (shmctl(shmid, IPC_RMID, 0) == -1) {
fprintf(stderr, "shmctl(IPC_RM)\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}

// shmdata.h
#include <string>

#ifndef __SHMDATA_H_HEADER
#define __SHMDATA_H_HEADER

#define TEXT_SZ 2048
struct shared_use_st {
int written; //标志位,非0:read;0:write
char timestamp[1];
};
#endif
 评论
评论插件加载失败
正在加载评论插件
由 Hexo 驱动 & 主题 Keep
访客数 访问量