共享内存实现进程间变量共享
·
在操作系统(OS)层面,进程间共享“全局变量”的核心方式是共享内存。这是一种由操作系统内核管理的进程间通信(IPC)机制,允许多个进程访问同一块物理内存区域,从而实现高效的数据共享。
共享内存方式详解
| 特性 | 描述 |
|---|---|
| 核心机制 | 操作系统内核分配一块物理内存,并将其映射到多个进程各自的虚拟地址空间中。 |
| 数据位置 | 共享数据物理上位于内核管理的共享内存段中,逻辑上存在于各进程映射的用户空间地址。 |
| 访问方式 | 进程通过指针直接读写映射后的内存地址,如同访问普通变量,无需系统调用介入,速度极快。 |
| 同步要求 | 必须配合使用信号量、互斥锁等同步机制,以防止并发读写导致的数据竞争。 |
| 典型应用 | 高性能计算、数据库缓存、大型软件模块间通信。 |
实现示例:C语言使用POSIX共享内存
以下代码展示了两个进程如何通过共享内存共享一个整型变量。
进程A:创建并写入共享内存 (writer.c)
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
int main() {
const char *name = "MY_SHARED_VAR"; // 共享内存对象标识 const int SIZE = sizeof(int);
// 1. 创建或打开共享内存对象 int shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
// 2. 设置共享内存大小
ftruncate(shm_fd, SIZE);
// 3. 将共享内存映射到进程地址空间 int *shared_var = (int *)mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
// 4. 写入数据(如同修改全局变量)
*shared_var = 100;
printf("进程A写入: shared_var = %d
", *shared_var);
// 保持映射,等待进程B读取
getchar(); // 按回车键继续,以便进程B有时间读取
// 5. 清理:解除映射并删除共享对象 munmap(shared_var, SIZE);
close(shm_fd);
shm_unlink(name);
return 0;
}
进程B:读取共享内存 (reader.c)
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
int main() {
const char *name = "MY_SHARED_VAR"; // 必须与进程A的名称一致
const int SIZE = sizeof(int);
// 1. 打开已存在的共享内存对象 int shm_fd = shm_open(name, O_RDWR, 0666);
// 2. 映射到进程地址空间
int *shared_var = (int *)mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
// 3. 读取数据 printf("进程B读取: shared_var = %d
", *shared_var);
// 4. 可选:修改数据
*shared_var += 1;
printf("进程B修改后: shared_var = %d
", *shared_var);
// 5. 解除映射
munmap(shared_var, SIZE);
close(shm_fd);
return 0;
}
编译与运行命令:
# 编译,需要链接实时库(-lrt)
gcc writer.c -o writer -lrt
gcc reader.c -o reader -lrt
# 先在一个终端运行写入进程
./writer
# 然后在另一个终端运行读取进程
./reader
高级语言封装示例:Python multiprocessing
Python的multiprocessing模块提供了基于共享内存的高级抽象,如Value和Array。
from multiprocessing import Process, Value, Array, Lock
import time
def increment_shared_counter(counter, lock):
"""子进程:安全地增加共享计数器"""
for _ in range(1000):
with lock: # 使用锁进行同步
counter.value += 1
if __name__ == '__main__':
# 创建共享内存中的整型变量和锁 shared_counter = Value('i', 0) # 'i' 表示有符号整型
lock = Lock()
# 创建两个进程并发修改共享变量
p1 = Process(target=increment_shared_counter, args=(shared_counter, lock))
p2 = Process(target=increment_shared_counter, args=(shared_counter, lock))
p1.start()
p2.start()
p1.join()
p2.join()
print(f"最终计数器值: {shared_counter.value}") # 正确输出应为 2000
此例中,shared_counter 是一个存储在共享内存中的整型变量,两个子进程通过Value对象访问同一物理内存位置。
与其他IPC方式的对比
| 共享方式 | 是否直接共享内存 | 数据位置 | 典型用途 |
|---|---|---|---|
| 共享内存 | 是,直接读写同一内存块。 | 内核共享内存段 | 高性能、大数据量实时共享。 |
| 消息队列/管道 | 否,通过内核缓冲区拷贝数据。 | 内核消息缓冲区 | 进程间流式或消息通信。 |
| 内存映射文件 | 是,通过映射同一文件到内存。 | 磁盘文件 | 大数据持久化共享或进程间通信。 |
| 网络套接字 | 否,通过协议栈序列化传输。 | 网络缓冲区 | 跨网络或本地进程通信。 |
结论:进程间共享“全局变量”最直接、高效的方式是共享内存,其本质是多个进程的虚拟地址空间映射到同一块由操作系统内核管理的物理内存区域。其他如消息传递等方式虽然也能交换数据,但并非严格意义上的“共享变量”,因为数据需要经过拷贝。
参考来源
- 多线程--局部变量和成员变量作用域分析
- java线程的堆空间共享,为什么线程共享堆空间?
- javaScript基础---(一):如何在网页中实现javaScript脚本语言
- linux虚拟机配置jdk环境变量
- LabVIEW 共享变量通讯方式
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)