进程2访问共享内存时数据为空的问题排查求助
共享内存跨进程读取异常问题
我开发了一个C语言应用,进程1负责将数据加载到共享内存空间,进程2访问该共享内存进行后续处理。进程1运行正常且已完成数据加载,但进程2读取共享内存结构体字段时所有值均为0。
通过GDB调试发现,进程1运行至main函数即将退出时,共享内存中的数据已正确填充且可访问;但在进程2中访问同一共享内存地址时,所有数据均显示为0。
进程1调试输出
##dnodes结构体指针指向的地址 (gdb) x /10xg &(g_ptr->dct_tu->dnodes) 0x7fff56fbe4b0: 0x00007fff859abc88 0x00007fffbfaee688 0x7fff56fbe4c0: 0x00007fffbfcd6b08 0x00007fffbe591a88 0x7fff56fbe4d0: 0x00007fffbf4d3e88 0x00007fffbfd9a008 0x7fff56fbe4e0: 0x00007fffed264e08 0x00007fffb2e76a88 0x7fff56fbe4f0: 0x00007fffb6b7fa88 0x00007fffb7320c88 ##dnodes指针指向地址0x7fff859abc88处的数据 (gdb) x /100dw &(g_ptr->dct_tu->dnodes[0]) 0x7fff859abc88: 0 0 68068068 0 0x7fff859abc98: 68068068 0 0 0 0x7fff859abca8: 0 0 68067 0 0x7fff859abcb8: 76066071 0 87078000 0 0x7fff859abcc8: 1575397555 319731 0 0 0x7fff859abcd8: 77066 0 76066066 0 0x7fff859abce8: 87088000 0 1575397556 319731
进程2调试输出
##dnodes结构体指针指向的地址 (gdb) x /10xg &(shmp->dct_tu->dnodes) 0x7fff5711e4b0: 0x00007fff859abc88 0x00007fffbfaee688 0x7fff5711e4c0: 0x00007fffbfcd6b08 0x00007fffbe591a88 0x7fff5711e4d0: 0x00007fffbf4d3e88 0x00007fffbfd9a008 0x7fff5711e4e0: 0x00007fffed264e08 0x00007fffb2e76a88 0x7fff5711e4f0: 0x00007fffb6b7fa88 0x00007fffb7320c88 ##dnodes指针指向地址0x7fff859abc88处的数据 (gdb) x /100dw &(shmp->dct_tu->dnodes[0]) 0x7fff859abc88: 0 0 0 0 0x7fff859abc98: 0 0 0 0 0x7fff859abca8: 0 0 0 0 0x7fff859abcb8: 0 0 0 0 0x7fff859abcc8: 0 0 0 0 0x7fff859abcd8: 0 0 0 0 0x7fff859abce8: 0 0 0 0 0x7fff859abcf8: 0 0 0 0 0x7fff859abd08: 0 0 0 0
ipcs命令输出
$ ipcs ------ Message Queues -------- key msqid owner perms used-bytes messages ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x2a0e4150 0 dev01 600 84016 2 ------ Semaphore Arrays -------- key semid owner perms nsems
问题原因分析
核心问题是**dnodes指针指向的是进程1的私有栈内存,而非共享内存区域**:
- 观察地址
0x7fff859abc88,这是Linux用户态栈的典型地址范围(通常以0x7fff开头) - 每个进程拥有独立的虚拟地址空间,同一虚拟地址在不同进程中对应完全不同的物理内存页
- 进程1中填充的是自身栈上的数据,进程2访问相同虚拟地址时,对应的是自己进程的未初始化栈内存,因此显示全0
- 你在共享内存中仅存储了指向进程1私有内存的指针,实际数据根本没放入共享内存
解决方案
- 如果
dnodes数组大小固定,直接将其嵌入共享内存的结构体中,避免使用指针 - 如果数据大小动态,需要在共享内存段内分配存储空间存放实际数据,不能使用进程私有内存的指针
- 确保所有需要跨进程共享的数据都位于共享内存的地址范围内,禁止在共享内存中存放指向进程私有内存(栈/堆)的指针
内容的提问来源于stack exchange,提问作者user3363546
相关产品推荐
相关产品推荐

