You need to enable JavaScript to run this app. C语言共享内存中SharedMem结构体内置信号量初始化报错咨询
优惠活动
大模型
产品
解决方案
定价
更多

C语言共享内存中SharedMem结构体内置信号量初始化报错咨询

报错原因定位

你当前的调用存在两处参数错误,直接导致初始化失败:

  • 第一处地址取指错误:sem_init(&shm, 0, 1)中,shm本身是指向SharedMem结构体的指针,&shm取的是这个指针变量本身的栈内存地址,并非结构体内部sem成员的地址,类型与sem_init要求的*sem_t**参数完全不匹配,会直接触发参数校验报错。
  • 第二处共享模式参数错误:sem_init的第二个参数pshared传0时,代表该信号量为同进程内的线程共享使用,此时信号量的存储位置必须是进程私有地址空间;如果要实现多进程通过共享内存访问同一个信号量,该参数必须传非0值,明确告知内核该信号量为跨进程共享模式。
修正后的实现方案

核心调整逻辑:

  1. 仅由首次创建共享内存段的进程执行信号量初始化,避免多进程挂载时重复初始化覆盖信号量的计数值,破坏互斥逻辑。
  2. 严格按照参数要求传入对应值:第一个参数传入共享内存内sem成员的地址,第二个参数传1标记跨进程共享,第三个参数传入需要的信号量初始值。

修正后的核心代码示例:

#include <errno.h>
// 标记当前进程是否是共享内存段的首次创建者
int is_new_segment = 0;

// 先以排他模式尝试新建共享内存
int shmid = shmget(sharedMemKey, sizeof(SharedMem), IPC_CREAT | IPC_EXCL | 0666);
if (shmid < 0) {
    // 排他创建失败说明共享内存段已存在,直接获取已有段
    if (errno == EEXIST) {
        shmid = shmget(sharedMemKey, sizeof(SharedMem), 0666);
        if (shmid < 0) {
            printf("共享内存获取失败\n");
            return 1;
        }
    } else {
        printf("共享内存创建失败\n");
        return 1;
    }
} else {
    is_new_segment = 1;
}

// 挂载共享内存到当前进程地址空间
SharedMem *shm = shmat(shmid, NULL, 0);
if (shm == (SharedMem *)-1) {
    printf("共享内存挂载失败\n");
    return 1;
}
shm->shmid = shmid;

// 仅首次创建段的进程负责初始化信号量
if (is_new_segment) {
    // 正确的sem_init调用:传入结构体内部sem成员地址,标记跨进程共享,初始值1
    if (sem_init(&shm->sem, 1, 1) < 0) {
        printf("信号量初始化失败,错误码:%d\n", errno);
        // 初始化失败时清理已创建的共享内存,避免资源泄漏
        shmctl(shmid, IPC_RMID, NULL);
        return 1;
    }
}
注意事项
  • 跨进程共享信号量依赖内核的POSIX信号量支持,需要确保运行环境支持pshared非0的共享模式。
  • 共享内存段生命周期结束时,需要先调用sem_destroy(&shm->sem)释放信号量资源,再调用shmctl(shmid, IPC_RMID, NULL)删除共享内存段。
  • 禁止多个进程挂载共享内存后重复执行sem_init,否则会覆盖信号量的当前运行计数值,导致互斥逻辑失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.22 10:15:04