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

Linux下C语言共享内存仅在系统调用后更新的问题咨询

共享内存更新无法同步的问题解决

问题描述

编写了两个小型C程序:Server通过shm_open创建共享内存并循环写入数据;Client读取该共享内存并显示当前值。但Client无法看到Server的更新,除非Server调用sleep或printf等系统调用。仅当Server.c中取消sleep(1)注释时程序才能正常工作。

Server.c

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

int main (int argc, char *argv[]){

    int fd = shm_open("/SHM_TEST",  O_RDWR | O_CREAT, S_IRWXU);
    ftruncate(fd, 4096);
    
    unsigned char *ptr = mmap(0,4096,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,fd,0);
    
    while(1){
        for(unsigned short int i=0;i<256;i++){
            *ptr = i;
            //sleep(1);
        }
    }
}

Client.c

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

int main (int argc, char *argv[]){

    int fd = shm_open("/SHM_TEST",  O_RDWR, S_IRWXU);
    unsigned char *ptr = mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    
    int i = 0;
    while(1){
        printf("%d--%d\n", *ptr, i);
        i++;
    }
}

原因分析

你的猜测正确,这是CPU缓存一致性机制导致的问题,共享内存确实映射到了同一物理内存。CPU为提升性能,会把频繁访问的内存数据加载到本地高速缓存中,Server的写入操作仅修改了自身CPU缓存里的数据,没有及时同步到主存,导致Client读取的仍是旧的主存数据。而sleep、printf这类系统调用会触发内核态切换,此时CPU会自动刷新缓存到主存,所以取消sleep注释后Client能读到更新。

解决方法

无需依赖系统调用,通过内存屏障即可强制缓存同步:

在Server的写入操作后添加GCC内置的内存屏障函数__sync_synchronize(),它会强制CPU将缓存中的数据写回主存,并使其他CPU的对应缓存失效,确保Client能读取到最新值。修改后的Server循环代码如下:

while(1){
    for(unsigned short int i=0;i<256;i++){
        *ptr = i;
        __sync_synchronize(); // 触发缓存同步,无需系统调用
    }
}

另外也可以将共享内存标记为非缓存区域,但这会大幅降低内存访问性能,不推荐使用。

内容的提问来源于stack exchange,提问作者bearIO

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 09:21:00