首页 > 解决方案 > Unix Semaphore - unable to set initial value

问题描述

I am trying to initiate a UNIX semaphore so that I can use it to control two processes.

I copied the sem_init function from this example. I removed the pshared parameter because it was not used in the function and corrected int * sem to int * semid assuming this was a mistake.

#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;
}

The program prints Unable to set semaphore value: permission denied. I also copied the first main function from this example and it prints Cannot set semaphore value.

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?

Also another thing. 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.

If you could let me know what the 0666 does that would be great because none of the examples explain it.

标签: c++semaphore

解决方案


The problems with

*semid = semget(KEY, 1, IPC_CREAT | IPC_EXCL | 0666);

and

int ret = semctl( *semid, 0, SETVAL, value);

are almost certainly caused because the Sys V semaphore identified by *semid already exists with incorrect permissions, likely because an earlier creation left off the 0666 permissions. Since the semaphore id already exists, you can't attach to it with the IPC_EXCL flag set.

Assuming you're running on Linux, the ipcs -s command will show you the existing Sys V semaphores. You can then use the ipcrm command to remove the semaphore(s) with incorrect permissions and start over.


推荐阅读