c++ - Unix 信号量 - 无法设置初始值

标签 c++ semaphore

我正在尝试启动一个 UNIX 信号量,以便我可以使用它来控制两个进程。

我从 this 复制了 sem_init 函数例子。我删除了 pshared 参数,因为它没有在函数中使用,并将 int * sem 更正为 int * semid 假设这是一个错误。

#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <errno.h>

/* The semaphore key is an arbitrary long integer which serves as an
   external identifier by which the semaphore is known to any program
   that wishes to use it. */

using namespace std;

#define KEY (1492)

int sem_init(int* semid, unsigned int value) {
    /* get the semaphore */
    *semid = semget(KEY, 1, IPC_CREAT);
    if (*semid == -1) {
        printf("Unable to obtain semaphore.\n");
        return -1;
    } 

    int ret = semctl( *semid, 0, SETVAL, value);
    if (ret == -1) {
        printf("Unable to set semaphore value: %s\n", strerror(errno));
        return -1;
    }
    return ret;
}

int main(void) {
    int* semid = (int*) malloc(sizeof(int));
    sem_init(semid, 1);

    return 0;
}

程序打印Unable to set semaphore value: permission denied。我还从 this 复制了第一个主要功能示例并打印 Cannot set semaphore value

我应该提到的一件事是,似乎有一些进程在后台运行,从我以前运行的程序开始,但它不会让我终止它们(它说不允许操作),所以也许是信号量已经初始化,它不会让我重新初始化它吗?

还有一件事。第一个示例通过 IPC_CREAT | IPC_EXCL | 0666sem_get,但是当我这样做时 semget 返回 -1。它仅在传递 IPC_CREAT 时有效。

如果您能让我知道 0666 的作用,那就太好了,因为没有一个示例可以解释它。

最佳答案

The program prints Unable to set semaphore value: permission denied.

那是因为如果您调用的 semget() 实际上创建了一个新的信号量集,那么它创建它时没有任何人的访问权限。您可能想要更像这样的东西:

*semid = semget(KEY, 1, IPC_CREAT | S_IRUSR | S_IWUSR);

这将分配模式 0600;根据需要添加更多权限。 S_ 宏记录在 open() 函数中。

One thing I should mention is that there does seem to be processes running in the background from previous times that I have run the program, but it won't let me terminate them (it says operation not permitted), so maybe the semaphore is already initialized and it won't let me reinitialize it?

我看不出您提供的特定程序会继续在后台运行的任何原因,但它创建的任何信号量集都具有内核持久性:它一直存在,直到明确删除,这将超过您的特定程序的终止。您应该能够使用 ipcs 命令获取当前信号量的列表,并使用 ipcrm 命令删除旧信号量。这些可能需要 root 权限。

The first example passes IPC_CREAT | IPC_EXCL | 0666 to sem_get, but when I do this semget returns -1. It only works if just IPC_CREAT is passed.

这又是您的信号量设置比程序长寿的问题。当您指定 IPC_EXCL 时,如果具有指定键的信号量集已经存在,则您明确请求调用失败(返回 -1),因此调用不会重新创建。在省略 IPC_EXCL 时包含模式位(0666)应该没有害处,但它们仅在创建新的信号量集时有效。我在上面引用的 S_IRUSRS_IWUSR 常量表示两个特定的模式位,通常我建议使用常量而不是对模式进行数字编码。

顺便说一句,请注意 ftok() 函数是获取用于标识信号量集的键值的常规方法。

关于c++ - Unix 信号量 - 无法设置初始值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55244796/

相关文章:

C:信号处理和信号量

c++ - 如何将现有矢量化函数对应于英特尔编译器自动矢量化的现有标量函数

java - 为什么这个线程(WriteData)没有执行它的功能?

c - 错误: field ‘rwsem’ has incomplete type

c - 就 CPU 时间而言,等待互斥量与等待信号量

windows - 如何等待/阻塞直到信号量值在 Windows 中达到 0

c++ - 如何删除排序 vector 中的重复项

c++ - 在不为数组分配内存的情况下工作

c++ - 编译时 C++ 项目抛出错误 C2228,这不是预期的,因为控件在运行时未到达该点

c++ - 大小为 0 的数组