You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux中使用/dev/shm共享内存对象的IPC机制延迟问题咨询

多核心进程共享内存可见性问题的解决方案

你的问题本质不是内核刷写共享内存的延迟,而是CPU缓存一致性与内存可见性问题:每个CPU核心拥有独立的L1/L2缓存,当process1写入共享内存时,数据会先存在当前核心的缓存中,若未同步到其他核心的缓存,process2读取时就会拿到旧值。msync仅用于将内存映射的数据刷写到磁盘(/dev/shm是内存文件系统,无实际磁盘写入),因此无法解决缓存同步问题。

以下是几种可靠的解决方法:

1. 使用原子操作(推荐,最轻量)

利用C标准库的stdatomic.h或编译器内置的原子操作函数,确保写操作的内存可见性,同时避免数据竞争。原子操作会自动插入内存屏障,强制缓存同步。

Process1 代码片段

#include <stdatomic.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

int main() {
    int fd = shm_open("/transfer_info", O_RDWR | O_CREAT, 0666);
    ftruncate(fd, sizeof(atomic_char));
    atomic_char *shared_data = mmap(NULL, sizeof(atomic_char), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    
    // 写入'1',release序保证写操作对其他核心可见
    atomic_store_explicit(shared_data, '1', memory_order_release);
    sleep(1);
    // 写入'0'
    atomic_store_explicit(shared_data, '0', memory_order_release);
    
    munmap(shared_data, sizeof(atomic_char));
    close(fd);
    return 0;
}

Process2 代码片段

#include <stdatomic.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>

int main() {
    int fd = shm_open("/transfer_info", O_RDWR, 0666);
    atomic_char *shared_data = mmap(NULL, sizeof(atomic_char), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    
    char val;
    // 读取直到拿到'1',acquire序保证读取到最新值
    do {
        val = atomic_load_explicit(shared_data, memory_order_acquire);
    } while (val != '1');
    printf("读到值: '1'\n");
    
    // 读取直到拿到'0'
    do {
        val = atomic_load_explicit(shared_data, memory_order_acquire);
    } while (val != '0');
    printf("读到值: '0'\n");
    
    munmap(shared_data, sizeof(atomic_char));
    close(fd);
    shm_unlink("/transfer_info");
    return 0;
}

2. 手动插入内存屏障

针对不同CPU平台插入对应的内存屏障指令,强制缓存同步。这种方式需要注意平台兼容性(如x86用mfence,ARM用dsb)。

Process1 写后加屏障

shared_data[0] = '1';
// x86平台内存屏障,确保写操作同步到所有核心缓存
asm volatile("mfence" ::: "memory");

Process2 读前加屏障

// x86平台读屏障,确保读取最新的缓存数据
asm volatile("lfence" ::: "memory");
char val = shared_data[0];

3. 使用跨进程互斥锁

通过POSIX互斥锁保护共享内存的读写操作,互斥锁的加锁/解锁操作会自动触发内存屏障,保证缓存同步。适合更复杂的共享数据场景。

Process1 代码片段

#include <pthread.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

typedef struct {
    pthread_mutex_t mutex;
    char data;
} SharedData;

int main() {
    int fd = shm_open("/transfer_info", O_RDWR | O_CREAT, 0666);
    ftruncate(fd, sizeof(SharedData));
    SharedData *shared = mmap(NULL, sizeof(SharedData), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    
    // 初始化跨进程互斥锁
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
    pthread_mutex_init(&shared->mutex, &attr);
    
    // 写'1'
    pthread_mutex_lock(&shared->mutex);
    shared->data = '1';
    pthread_mutex_unlock(&shared->mutex);
    
    sleep(1);
    
    // 写'0'
    pthread_mutex_lock(&shared->mutex);
    shared->data = '0';
    pthread_mutex_unlock(&shared->mutex);
    
    munmap(shared, sizeof(SharedData));
    close(fd);
    return 0;
}

Process2 代码片段

#include <pthread.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>

typedef struct {
    pthread_mutex_t mutex;
    char data;
} SharedData;

int main() {
    int fd = shm_open("/transfer_info", O_RDWR, 0666);
    SharedData *shared = mmap(NULL, sizeof(SharedData), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    
    char val;
    // 读'1'
    do {
        pthread_mutex_lock(&shared->mutex);
        val = shared->data;
        pthread_mutex_unlock(&shared->mutex);
    } while (val != '1');
    printf("读到值: '1'\n");
    
    // 读'0'
    do {
        pthread_mutex_lock(&shared->mutex);
        val = shared->data;
        pthread_mutex_unlock(&shared->mutex);
    } while (val != '0');
    printf("读到值: '0'\n");
    
    pthread_mutex_destroy(&shared->mutex);
    munmap(shared, sizeof(SharedData));
    close(fd);
    shm_unlink("/transfer_info");
    return 0;
}

内容的提问来源于stack exchange,提问作者Pavankumar S V

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 10:43:21