在操作系统(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模块提供了基于共享内存的高级抽象,如ValueArray

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方式的对比

共享方式是否直接共享内存数据位置典型用途
共享内存,直接读写同一内存块。内核共享内存段高性能、大数据量实时共享。
消息队列/管道否,通过内核缓冲区拷贝数据。内核消息缓冲区进程间流式或消息通信。
内存映射文件是,通过映射同一文件到内存。磁盘文件大数据持久化共享或进程间通信。
网络套接字否,通过协议栈序列化传输。网络缓冲区跨网络或本地进程通信。

结论:进程间共享“全局变量”最直接、高效的方式是共享内存,其本质是多个进程的虚拟地址空间映射到同一块由操作系统内核管理的物理内存区域。其他如消息传递等方式虽然也能交换数据,但并非严格意义上的“共享变量”,因为数据需要经过拷贝。


参考来源

 

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐