信号量值初始化为-1?

Semaphore value initialized to -1?

我正在尝试为一些共享内存初始化二进制信号量。我想不通为什么我挂在一个 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 

实际上,man page for semctl 告诉您 return 值为 -1 表示出现错误。

要获取错误,请使用 strerror printf( "%s", strerror(errno) );

不要忘记 #include <errno.h>#include <string.h>

你有两个错误。你的第一个错误是,与 C 中一样,由 semget 创建的信号量数组是 0 索引的;所以,如果你只创建一个信号量,semctl 的第二个参数 semid 应该是 0,而不是 1。你从 semctl 返回的 -1 不是值信号量,但错误指示(您应该发现 errno == EINVAL)。

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

Upon creation, ...

  • the data structure associated with each semaphore in the set need not be initialized. The semctl() function with the command SETVAL or SETALL can be used to initialize each semaphore.

(强调我的)这意味着,您的代码不能依赖于首次创建时具有 any 特定值的新 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 的定义从文档中复制到您的代码中;它不是由任何 header.

提供的

如果您开始觉得这个 API 很糟糕,那么您是 100% 正确的。您可能会发现 semaphore.h API 更合意,但 不那么普遍。