Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I sync the outputs of two processes using a semaphore with C in Linux?

I have the following code:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>

#define SEMAPHORE 0

int main(int argc, char *argv[])
{
    int semid, pid, j = 10;
    struct sembuf operation;
    key_t key;

    key = ftok(argv[0], 'U');

    if ((semid = semget(key, 1, IPC_CREAT | 0600)) == -1)
    {
        perror("Error at semget");
        exit(-1);
    }
    semctl(semid, SEMAPHORE, SETVAL, 1);

    /* Child is created  */
    if ((pid = fork()) == -1)
    {
        perror("Error at fork");
        exit(-1);
    }
    else if (pid == 0)
    {
        /* Code corresponding to the child process  */
        while (j)
        {
            /* DOWN operation is performed at the semaphore  */
            operation.sem_flg = 0;
            operation.sem_op = -1;
            operation.sem_num = SEMAPHORE;

            semop(semid, &operation, 1);

            printf("I AM THE CHILD PROCESS, IMPRESSION: %d\n", j--);

            /* UP operation is performed at the semaphore  */
            operation.sem_op = 1;
            operation.sem_num = SEMAPHORE;
            semop(semid, &operation, 1);
        }
    }
    else
    {
        /* Code corresponding to the parent process */
        while (j)
        {
            /* DOWN operation is performed at the semaphore */
            operation.sem_flg = 0;
            operation.sem_op = -1;
            operation.sem_num = SEMAPHORE;

            semop(semid, &operation, 1);

            printf("I AM THE FATHER PROCESS, IMPRESSION: %d\n", j--);

            /* UP operation is performed at the semaphore */
            operation.sem_op = 1;
            operation.sem_num = SEMAPHORE;
            semop(semid, &operation, 1);
        }
    }
}

So I could expect the following output:

I AM THE FATHER PROCESS, IMPRESSION: 10
I AM THE CHILD PROCESS, IMPRESSION: 10
I AM THE FATHER PROCESS, IMPRESSION: 9
I AM THE CHILD PROCESS, IMPRESSION: 9
I AM THE FATHER PROCESS, IMPRESSION: 8
I AM THE CHILD PROCESS, IMPRESSION: 8
I AM THE FATHER PROCESS, IMPRESSION: 7
I AM THE CHILD PROCESS, IMPRESSION: 7
I AM THE FATHER PROCESS, IMPRESSION: 6
I AM THE CHILD PROCESS, IMPRESSION: 6
I AM THE FATHER PROCESS, IMPRESSION: 5
I AM THE CHILD PROCESS, IMPRESSION: 5
I AM THE FATHER PROCESS, IMPRESSION: 4
I AM THE CHILD PROCESS, IMPRESSION: 4
I AM THE FATHER PROCESS, IMPRESSION: 3
I AM THE CHILD PROCESS, IMPRESSION: 3
I AM THE FATHER PROCESS, IMPRESSION: 2
I AM THE CHILD PROCESS, IMPRESSION: 2
I AM THE FATHER PROCESS, IMPRESSION: 1
I AM THE CHILD PROCESS, IMPRESSION: 1

Or first the Child and then the father successively. However, I run it and the output it produces is as follows:

I AM THE FATHER PROCESS, IMPRESSION: 10
I AM THE FATHER PROCESS, IMPRESSION: 9
I AM THE FATHER PROCESS, IMPRESSION: 8
I AM THE FATHER PROCESS, IMPRESSION: 7
I AM THE FATHER PROCESS, IMPRESSION: 6
I AM THE FATHER PROCESS, IMPRESSION: 5
I AM THE FATHER PROCESS, IMPRESSION: 4
I AM THE FATHER PROCESS, IMPRESSION: 3
I AM THE FATHER PROCESS, IMPRESSION: 2
I AM THE FATHER PROCESS, IMPRESSION: 1
I AM THE CHILD PROCESS, IMPRESSION: 10
I AM THE CHILD PROCESS, IMPRESSION: 9
I AM THE CHILD PROCESS, IMPRESSION: 8
I AM THE CHILD PROCESS, IMPRESSION: 7
I AM THE CHILD PROCESS, IMPRESSION: 6
I AM THE CHILD PROCESS, IMPRESSION: 5
I AM THE CHILD PROCESS, IMPRESSION: 4
I AM THE CHILD PROCESS, IMPRESSION: 3
I AM THE CHILD PROCESS, IMPRESSION: 2
I AM THE CHILD PROCESS, IMPRESSION: 1

Or sometimes this impression comes out, but I don't get the expected one:

I AM THE FATHER PROCESS, IMPRESSION: 10
I AM THE FATHER PROCESS, IMPRESSION: 9
I AM THE CHILD PROCESS, IMPRESSION: 10
I AM THE CHILD PROCESS, IMPRESSION: 9
I AM THE CHILD PROCESS, IMPRESSION: 8
I AM THE CHILD PROCESS, IMPRESSION: 7
I AM THE CHILD PROCESS, IMPRESSION: 6
I AM THE CHILD PROCESS, IMPRESSION: 5
I AM THE FATHER PROCESS, IMPRESSION: 8
I AM THE FATHER PROCESS, IMPRESSION: 7
I AM THE FATHER PROCESS, IMPRESSION: 6
I AM THE CHILD PROCESS, IMPRESSION: 4
I AM THE CHILD PROCESS, IMPRESSION: 3
I AM THE CHILD PROCESS, IMPRESSION: 2
I AM THE CHILD PROCESS, IMPRESSION: 1
I AM THE FATHER PROCESS, IMPRESSION: 5
I AM THE FATHER PROCESS, IMPRESSION: 4
I AM THE FATHER PROCESS, IMPRESSION: 3
I AM THE FATHER PROCESS, IMPRESSION: 2
I AM THE FATHER PROCESS, IMPRESSION: 1

I understand that the order of execution of the processes depends directly on the operating system, but isn't it supposed that when one of the two processes does UP, the other should enter to run?

So my question is, what exactly is going on here?

like image 929
DDTORRES055 Avatar asked Nov 26 '25 23:11

DDTORRES055


1 Answers

Let P (sem) denote the down operation for semaphore sem and V (sem) denote the up operation for the semaphore sem.

Currently, your code is like,

// semaphore s1
s1 = 1;
// parent process
P (s1);  
 // work
V (s1)

// child process
P (s1)
  // work
V (s1)

So what is being said here is that only one process can do the "work" at a time and the kernel is following that.

To synchronize output of two process, the following needs to be done.

// semaphores, sem-parent, sem-child
sem-parent = 1; sem-child = 0;

// parent process
P (sem-parent);
   // work
V (sem-child);

// child process
P (sem-child);
   // work
V (sem-parent);
like image 95
kjohri Avatar answered Nov 29 '25 13:11

kjohri