信号量值初始化为-1?

时间:2015-03-13 23:15:58

标签: c ipc semaphore

我正在尝试为某些共享内存初始化二进制信号量。我无法弄清楚为什么我挂在semop上获取信号量,最终发现信号量值为-1而且我等待了。我没有得到的是为什么信号量值初始化为-1开始。任何澄清这一点的帮助将不胜感激。

semID = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR); // create sem
int semval = semctl(semID, 1,GETVAL);

printf("After init Semaphore value = %d \n", semval);
printf("sem ID = %d \n", semID);

输出:

 After init semaphore value = -1 
 sem ID = 524304 

2 个答案:

答案 0 :(得分:4)

你有两个错误。你的第一个错误是,就像在C中一样,由semget创建的信号量数组是0索引的;所以,如果你只创建一个信号量,semctlsemid的第二个参数应为0,而不是1.你从semctl回来的-1不是信号量的值,但是错误指示(你应该找到errno == EINVAL)。

你的第二个错误更微妙。 The POSIX.1-2008 specification for semget说:

  

创作后......

     
      
  • 与集合中每个信号量相关联的数据结构无需初始化。使用命令SETVALSETALL的{​​{3}}函数可用于初始化每个信号量。
  •   

(强调我的)这意味着,您的代码在首次创建时不能依赖具有任何特定值的新SysV信号量。你必须做这样的事情:

semID = semget(IPC_PRIVATE, 1, S_IRUSR|S_IWUSR);
if (semID < 0) {
    perror("semget");
    return -1;
}

union semun arg;
arg.val = 0;
if (semctl(semID, 0, SETVAL, arg) == -1) {
    perror("semctl");
    return -1;
}

// only now is it safe to use the semaphore

请注意,您必须将文档中的union semun定义复制到您的代码中;它不是由任何标题提供的。

如果你开始觉得这个API很糟糕,那么你是100%正确的。您可能会发现semctl() API更适合,但 不太普遍。

答案 1 :(得分:2)

实际上,man page for semctl告诉您返回值为-1表示存在错误。

要使用strerror printf( "%s", strerror(errno) );

获取错误

别忘了#include <errno.h>#include <string.h>