Linux下多进程shm_open共享内存失败问题排查求助
共享内存跨进程访问问题排查
我用pthread编写了3个多线程程序,它们需要访问同一块共享内存:parent程序负责创建共享内存,另外两个是child程序。目前parent内部的两个线程(一个调用cond_wait、一个执行广播)协作正常,但把cond_wait线程的代码移植到child程序后无法正常运行。经排查确认child无法正确访问共享内存,推测问题出在父子进程创建/打开共享内存的代码实现上。
Parent 创建共享内存的代码
bool create_shared_object( shared_memory_t* shm) { const char* share_name = shared_memory_name; shm_unlink(share_name); shm->name = share_name; shm->fd = shm_open(shm->name, O_CREAT | O_EXCL | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO); if(shm->fd == -1){ fprintf(stderr, "shm_open(%s): %s (%d)\n", shm->name, strerror(errno), errno); return false; } if (ftruncate(shm->fd , MEMORY_SIZE)){ fprintf(stderr, "ftruncate(%s): %s (%d)\n", shm->name, strerror(errno), errno); return false; } shm = mmap(NULL, MEMORY_SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, shm->fd, 0); if (shm == MAP_FAILED){ fprintf(stderr, "mmap(%s, %zu): %s (%d)\n", shm->name, (size_t)MEMORY_SIZE, strerror(errno), errno); return false; } return true; }
Child 打开共享内存的代码
bool create_shared_object( shared_memory_t* shm) { const char* share_name = shared_memory_name; shm->name = share_name; shm->fd = shm_open(shm->name, O_RDWR, 0); if(shm->fd == -1){ fprintf(stderr, "shm_open(%s): %s (%d)\n", shm->name, strerror(errno), errno); return false; } shm = mmap(NULL, MEMORY_SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, shm->fd, 0); if (shm == MAP_FAILED){ fprintf(stderr, "mmap(%s, %zu): %s (%d)\n", shm->name, (size_t)MEMORY_SIZE, strerror(errno), errno); return false; } return true; }
shared_memory_t 结构体定义
typedef struct shm{ const char* name; int fd; shared_parking_t data; }shared_memory_t;
其他相关信息
- 每个文件中定义共享内存对象:
shared_memory_t shm; - 执行
ls -l /dev/shm显示对应的内存文件:-rwxr-xr-x 1 cab403 cab403 584 Sep 26 23:27 PARKING - 测试方式:通过循环打印parent修改的内存值验证child是否能访问共享内存,已根据之前的建议更新过代码,仍无法解决。
- 操作系统:Linux
问题根源与修复方案
核心问题1:mmap操作未正确映射到外部结构体
你的create_shared_object函数中,将mmap返回的地址赋值给了函数参数shm——这是值传递的错误用法。函数内部修改的只是局部指针副本,外部的shared_memory_t shm变量根本没有被映射到共享内存区域,函数结束后修改完全丢失。
核心问题2:共享内存大小与结构体不匹配
ftruncate设置的MEMORY_SIZE必须等于shared_memory_t的完整大小(或至少包含shared_parking_t data的全部内容),否则会出现内存越界或数据截断,导致跨进程访问异常。
修改后的Parent创建共享内存代码
bool create_shared_object(shared_memory_t* shm) { const char* share_name = shared_memory_name; // 注意:shm_unlink需确保无其他进程使用该共享内存时执行 shm_unlink(share_name); shm->name = share_name; shm->fd = shm_open(shm->name, O_CREAT | O_EXCL | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO); if(shm->fd == -1){ fprintf(stderr, "shm_open(%s): %s (%d)\n", shm->name, strerror(errno), errno); return false; } // 确保共享内存大小与结构体一致 if (ftruncate(shm->fd, sizeof(shared_memory_t))){ fprintf(stderr, "ftruncate(%s): %s (%d)\n", shm->name, strerror(errno), errno); close(shm->fd); shm_unlink(share_name); return false; } // 将共享内存映射到外部传入的shm结构体地址 void* mapped_addr = mmap(shm, sizeof(shared_memory_t), PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED, shm->fd, 0); if (mapped_addr == MAP_FAILED){ fprintf(stderr, "mmap(%s, %zu): %s (%d)\n", shm->name, sizeof(shared_memory_t), strerror(errno), errno); close(shm->fd); shm_unlink(share_name); return false; } return true; }
修改后的Child打开共享内存代码
bool create_shared_object(shared_memory_t* shm) { const char* share_name = shared_memory_name; shm->name = share_name; shm->fd = shm_open(shm->name, O_RDWR, 0); if(shm->fd == -1){ fprintf(stderr, "shm_open(%s): %s (%d)\n", shm->name, strerror(errno), errno); return false; } // 将共享内存映射到外部传入的shm结构体地址 void* mapped_addr = mmap(shm, sizeof(shared_memory_t), PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED, shm->fd, 0); if (mapped_addr == MAP_FAILED){ fprintf(stderr, "mmap(%s, %zu): %s (%d)\n", shm->name, sizeof(shared_memory_t), strerror(errno), errno); close(shm->fd); return false; } return true; }
额外注意事项
- 使用
MAP_FIXED时需确保shm指向的内存区域未被占用,避免覆盖其他数据;若不想用MAP_FIXED,可调整结构体设计,添加指针字段指向映射的共享内存区域。 - 共享内存中的条件变量和互斥锁必须设置进程共享属性(通过
pthread_mutexattr_setpshared和pthread_condattr_setpshared配置),否则跨进程无法正常同步。 - 进程退出时需调用
munmap解除映射、close关闭文件描述符;parent进程在不再需要共享内存时执行shm_unlink清理资源。
内容的提问来源于stack exchange,提问作者Clue Less
相关产品推荐
相关产品推荐

