c++ - 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.
解决方案
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.