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

为何semop()返回EINVAL而非预期的EIDRM错误?

信号量移除后semop返回EINVAL而非EIDRM的原因分析

你的代码如下:

int rc = 0;

key_t key = ftok("test.sh", 100);
if (key == -1) {
  std::cout << "ftok failed" << std::endl;
}
int sem_id = semget(key, 1, IPC_CREAT | (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
                                   S_IROTH | S_IWOTH));
if (sem_id == -1) {
  std::cout << "semget failed" << std::endl;
}

//removing semaphore set
union semun sem_union;
rc = semctl(sem_id, 1, IPC_RMID, sem_union);  
if (rc == -1) {
  std::cout << "semctl failed" << std::endl;
}

struct sembuf command_buf[2];
// Wait for 0
command_buf[0].sem_num = 0;
command_buf[0].sem_op  = 0;
command_buf[0].sem_flg = SEM_UNDO;
// Increment by 1
command_buf[1].sem_num = 0;
command_buf[1].sem_op  = 1;
command_buf[1].sem_flg = SEM_UNDO;

rc = semop(sem_id, command_buf, 2);
if (rc == -1) {
  std::cout << "errno=" << errno << std::endl;
}

执行后输出errno=22(EINVAL),但预期返回EIDRM,核心原因是两个错误码的触发场景存在明确边界:

  • EIDRM仅在阻塞阶段触发:当semop()调用已经进入阻塞状态(比如你的代码中第一个操作是等待信号量值为0,若此时信号量不为0则会阻塞),在阻塞过程中信号量集被移除,才会返回EIDRM错误。
  • EINVAL在无效标识符场景触发:你的代码是先调用semctl(IPC_RMID)移除信号量集,再立刻执行semop()。此时sem_id已经是无效的标识符,内核优先校验sem_id的有效性,发现无效后直接返回EINVAL错误。

另外补充:你在semctl中传入的第二个参数1虽超出信号量有效编号范围(你创建的信号量集仅1个信号量,编号从0开始),但IPC_RMID命令会忽略该参数,因此semctl应该已成功移除信号量集,可通过检查semctl的返回值rc确认这一点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 01:45:42