Reputation: 53
I'm trying to code an exercise in C Linux
where I have one semaphore with 2 spots and "n" processes entered by argument. I need that the first 2 processes use the semaphore using the 2 spots for 5 secs each and then leave the semaphore for the other remaining processes to do their stuff. The problem is that not all the other processes wait for the semaphore to be free and some of them show a semaphore error (look at the results at the bottom). I believe the problem is on the waits for the child processes, because I have a waitipid
and a wait
function, but I need that if there's a free spot in the semaphore, any child process running could use it. Here's the code:
//gcc SemaphoreExample.c -o s
//./s 5
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>
void semaphoreTask(int semid, int semnum, int semBusy)
{
struct sembuf data;
data.sem_num = semnum;
data.sem_flg = 0;
data.sem_op = semBusy;
if(semop(semid,&data,1) == -1)
{
printf("\nSemaphore Error\n");
exit(-1);
}
}
int main(int argc, char *argv[])
{
int i, fdSemaphore, quantity, fdsemctl, j;
pid_t pid[15];
system("clear");
if(argc-1 < 1)
{
printf("Some arguments are missing\n");
return EXIT_FAILURE;
}
printf("Number of arguments entered:\n\nargc: %d\n\nValues from the arguments:\n\n",argc-1);
for(i=0;i<argc;i++)
{
printf("argv[%d]: %s\n",i,argv[i]);
}
printf("\n\n");
fdSemaphore = semget(1234,1,IPC_CREAT|0777);
if(fdSemaphore == -1)
{
printf("\nError creating the Semaphore\n");
return EXIT_FAILURE;
}
fdsemctl = semctl(fdSemaphore,0,SETVAL,2);
if(fdsemctl == -1)
{
printf("\nError opening the Semaphore\n");
return EXIT_FAILURE;
}
quantity = atoi(argv[1]);
for(i=0;i<quantity;i++)
{
pid[i] = fork();
if(pid[i] == -1)
{
printf("\nError creating the Child Process\n");
return EXIT_FAILURE;
}
if(pid[i] == 0)
{
semaphoreTask(fdSemaphore,0,-1);
printf("\n[%d] I go to sleep\n",getpid());
sleep(5);
printf("\n[%d] I wake up\n",getpid());
semaphoreTask(fdSemaphore,0,1);
}
else
{
//printf("\nJust wait\n");
waitpid(pid[i],NULL,WNOHANG);
}
}
for(j=0;j<quantity;j++)
{
wait(NULL);
}
semctl(fdSemaphore,0,IPC_RMID);
return EXIT_SUCCESS;
}
This is the result I got:
Result:
Number of arguments entered:
argc: 1
Values from the arguments:
argv[0]: ./s
argv[1]: 5
[2845] I go to sleep
[2844] I go to sleep
[2845] I wake up
[2844] I wake up
Semaphore Error
[2843] I go to sleep
Semaphore Error
Semaphore Error
[2843] I wake up
Semaphore Error
Should I use wait
or waitpid
only?
Upvotes: 0
Views: 1199
Reputation: 1572
The problem is semaphores are getting removed by forked children.
After line
semaphoreTask(fdSemaphore,0,1);
add
exit(0);
Upvotes: 1
Reputation: 1572
It is much simpler to implement what you want if you use sem_post and sem_wait calls. I am on a OpenBSD system and I am assuming that Linux has the same thing.
Upvotes: 0