为啥 semget() 在 *创建* 信号量时会导致 EACCES 错误?

Posted

技术标签:

【中文标题】为啥 semget() 在 *创建* 信号量时会导致 EACCES 错误?【英文标题】:Why does semget() cause an EACCES error when *creating* a semaphore?为什么 semget() 在 *创建* 信号量时会导致 EACCES 错误? 【发布时间】:2011-11-13 04:37:50 【问题描述】:

我必须为 C++ 项目创建一个信号量数组。我不是从main() 打电话给semget();我有一个单独的方法让它更容易,尽管main.cpp 中有一个方法。当我的程序到达 semget(semkey,nsems,0666|IPC_CREAT) 时,它返回 -1 并带有 EACCES errno,这显然意味着“key 存在信号量标识符,但不会授予 semflg 的低 9 位指定的操作权限。”

我已经用 GDB 反复检查了我的代码。 semget() 的所有三个参数看起来都正确,这是程序调用 semget() 的第一个点,因此信号量不存在;我什至跑了ipcs -s 来确定。我在main.cpp 的顶部有#include <sys/sem.h>

这里发生了什么?我已经创建并附加了一个共享内存段,这可能与它有关吗?我看不出来。

【问题讨论】:

重启后第一次能正常工作吗? 我没试过。那会影响吗?为什么? 好吧,用ipcs 清理应该可以解决问题,但可以肯定的是,重新启动系统肯定会清理任何剩余的共享资源(信号量、共享内存等...) ...嗯。那成功了。谢谢! 【参考方案1】:

来自手册:

 EACCES A semaphore set exists for key, but the calling process does not have permission to 
        access the set, and does not have the CAP_IPC_OWNER capability.

提醒一下,由于信号量是系统对象,因此只有在为此显式发出系统调用时才会将其删除。 (semctlIPC_RMIDipcrm 术语命令)。 此外,semkey 必须是唯一的(例如从ftok() 函数中检索),或者在您第一次调用semget 之前,可能有另一个程序创建了它。因为它会存在,你会捕获所谓的EACCES 错误,因为并非所有程序都像你一样使用信号量的 0666 权限。

重启会刷新共享对象池(信号量、共享内存段、消息队列):

#!/bin/bash
for i in `ipcs -s | cut -f 2 -d ' '`
do
   ipcrm -s $i
done

for i in `ipcs -m | cut -f 2 -d ' '`
do
   ipcrm -m $i
done

for i in `ipcs -q | cut -f 2 -d ' '`
do
   ipcrm -q $i
done

【讨论】:

以上是关于为啥 semget() 在 *创建* 信号量时会导致 EACCES 错误?的主要内容,如果未能解决你的问题,请参考以下文章

Linux进程间通信 -- 信号量 semget()semop()semctl()

信号量的基本概念与使用semget,semop

使用信号量实现有限缓冲区的生产者和消费者问题(使用fork(),semget()等函数,能在GCC下运行)

为啥当我发出信号时会出现分段错误

为啥企业微信创建企业失败

详解linux进程间通信-消息队列