I am trying to create an array of N named POSIX semaphores in C. But I am having trouble unlinking and closing them. I need to use an array of semaphores because each semaphore will represent a segment of a text file that will later go into shared memory.
I am doing something very similar to this post but it is not working. Maybe the problem is in the creation of the semaphores? Is there another way I could do this?
sem_t* semaphores[N];
for(int i = 0; i < N; i ){
char buf[100];
sprintf(buf, "s%d", i); // Give a unique name to each semaphore
semaphores[i] = sem_open(buf, O_CREAT | O_EXCL, SEM_PERMS, INITIAL_VALUE);
}
for(int i = 0; i < N; i ){
if(sem_unlink((void*)semaphores[i]) < 0){
perror("sem_unlink(0) failed OVER HERE");
exit(EXIT_FAILURE);
}
}
for(int i = 0; i < N; i ){
if(sem_close(semaphores[i]) < 0){
perror("sem_close(0) failed HERE");
exit(EXIT_FAILURE);
}
}
The error message I am getting is:
sem_unlink(0) failed OVER HERE: No such file or directory
CodePudding user response:
While sem_close(3)
takes a sem_t *
argument, sem_unlink(3)
takes the name of the semaphore as a const char *
.
Retain the names of your semaphores, so that they may be passed to sem_unlink(3)
later. The example below uses an array of structures to do so.
Additionally, per sem_overview(7)
, semaphore names should begin with a leading /
.
#include <fcntl.h>
#include <semaphore.h>
#include <stdio.h>
#define INITIAL_VALUE 1
#define N 8
#define SEM_PERMS 0666
int main(void)
{
struct {
char name[128];
sem_t *sem;
} semaphores[N];
for (size_t i = 0; i < N; i ) {
sprintf(semaphores[i].name, "/a-semaphore%zu", i);
semaphores[i].sem = sem_open(semaphores[i].name,
O_CREAT | O_EXCL, SEM_PERMS, INITIAL_VALUE);
if (SEM_FAILED == semaphores[i].sem)
perror(semaphores[i].name);
}
for (size_t i = 0; i < N; i )
if (sem_unlink(semaphores[i].name) < 0)
perror(semaphores[i].name);
for (size_t i = 0; i < N; i )
if (sem_close(semaphores[i].sem) < 0)
perror(semaphores[i].name);
}
As John points out below, storing each name is not necessarily required. Since the names are algorithmically generated, you could regenerate them from the same template when they are needed again.
A cursory example:
#include <fcntl.h>
#include <semaphore.h>
#include <stdio.h>
#define INITIAL_VALUE 1
#define N 8
#define SEM_PERMS 0666
void namegen(char *dst, size_t suffix)
{
sprintf(dst, "/a-semaphore%zu", suffix);
}
int main(void)
{
sem_t *semaphores[N];
for (size_t i = 0; i < N; i ) {
char name[128];
namegen(name, i);
semaphores[i] = sem_open(name,
O_CREAT | O_EXCL, SEM_PERMS, INITIAL_VALUE);
if (SEM_FAILED == semaphores[i])
perror(name);
}
for (size_t i = 0; i < N; i ) {
char name[128];
namegen(name, i);
if (sem_unlink(name) < 0)
perror(name);
if (sem_close(semaphores[i]) < 0)
perror(name);
}
}