Im trying to learn semaphores and how they work between processes, so i wanted to create a program that prints 10 times the string "abcd" from two separate for() loops. One for() contains the "ab" string while the other one contains the "cd" string. I thought the code was fine but apparently its not. I would appreciate if you could point out anything wrong or if i got something misunderstood.
Here's the code:
int main(void)
{
int i;
char *p;
sem_t *sem; //First semaphore
sem_t *sem2; //Second semaphore
//create, initialize semaphores
sem = sem_open("/semaphore1", O_CREAT, 0644, 1);
sem2 = sem_open("/semaphore2", O_CREAT, 0644, 1);
if (fork()) //Child process
{
for (i=0;i<10;i++)
{
sem_wait(sem2); //Lock the semaphore
for (p="ab"; *p; p++)
{
write(1, p, 1);
usleep(100);
}
sem_post(sem); //Release the semaphore lock
}
wait(NULL);
}
else //Parent process
{
for (i=0;i<10;i++)
{
sem_wait(sem); //Lock the semaphore
for (p="cd\n"; *p; p++)
{
write(1, p, 1);
usleep(100);
}
sem_post(sem2); //Release the semaphore lock
}
}
//Close the Semaphores
sem_close(sem);
sem_unlink("/semaphore1");
sem_close(sem2);
sem_unlink("/semaphore2");
return 0;
}
And one of the outputs:
abcd
cadb
cadb
cadb
cabd
cabd
cabd
cadb
cabd
cadb
As noted in a comment, you need to initialize the first semaphore (renamed sem1
for symmetry with sem2
in the code below) to 0
instead of 1
so that the parent process gets to go first.
The child and parent process comments were misplaced (the parent gets a non-zero result from fork()
and so works in the if
). This version produces the desired output even without any calls to usleep()
. Nominally, only one of the processes needs to use sem_close()
and sem_unlink()
, but since you don't check for or report any errors, you don't notice the calls that fail.
#include <stdio.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
int i;
char *p;
sem_t *sem1; // First semaphore
sem_t *sem2; // Second semaphore
// create, initialize semaphores
sem1 = sem_open("/semaphore1", O_CREAT, 0644, 0);
sem2 = sem_open("/semaphore2", O_CREAT, 0644, 1);
if (fork()) // Parent process
{
for (i = 0; i < 10; i++)
{
sem_wait(sem2); // Lock the semaphore
for (p = "ab"; *p; p++)
{
write(1, p, 1);
//usleep(100);
}
sem_post(sem1); // Release the semaphore lock
}
wait(NULL);
}
else // Child process
{
for (i = 0; i < 10; i++)
{
sem_wait(sem1); // Lock the semaphore
for (p = "cd\n"; *p; p++)
{
write(1, p, 1);
//usleep(100);
}
sem_post(sem2); // Release the semaphore lock
}
}
// Close the Semaphores
sem_close(sem1);
sem_unlink("/semaphore1");
sem_close(sem2);
sem_unlink("/semaphore2");
return 0;
}
Example output:
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd