Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Synchronizing two child processes with semaphores in c

I have to create a program that synchronizes two processes each printing only a single letter so that whenever we observe the output of the program, the difference between the amount of "A" and "B" is no greater than 2.

So this would be accepted:

BAABBAABBABA

this wouldn't be because it prints 4 B's and only 2 A's:

ABBABB

So for starters i decided to use the POSIX semaphores. I created two semaphores , giving them all the permissions using the sem_open Then i created two child processes and for each child process i open the semaphores i created as described in the man page for sem_open and manipulate them.

I don't think it's the logic of the sem_post and sem_wait that's at fault here, since the program seems to ignore them.

So my question is. What goes wrong?

Edit: I don't really need the solution to the problem. Some guidance alone would be much appreciated and welcoming as an answer. Thank you in advance!

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <semaphore.h>

int main(void){



  sem_t *semA = sem_open("/semA", O_CREAT|O_EXCL, S_IRWXU | S_IRWXG | S_IRWXO, 0);   //Initialize semaphore(= 0) for process A
  sem_t *semB = sem_open("/semB", O_CREAT|O_EXCL, S_IRWXU | S_IRWXG | S_IRWXO, 0);   //Initialize semaphore(= 0) for process B


  if (fork()){      // parent process
    if(fork()){}
    else{
      sem_t *childsemA = sem_open("/semA", 0);
      sem_t *childsemB = sem_open("/semB", 0);
      while(1){
        printf("A");
        sem_post(childsemB);
        sem_wait(childsemA);
      }
    }
  }
  else{
    sem_t *childsemA = sem_open("/semA", 0);
    sem_t *childsemB = sem_open("/semB", 0);
    while(1){
      printf("B");    // child2 process
      sem_post(childsemA);
      sem_wait(childsemB);
    }
  }

  return 0;
}

Output:

enter image description here

like image 676
Nikos Tzianas Avatar asked Jan 10 '19 20:01

Nikos Tzianas


People also ask

What are the semaphores in process synchronization?

Semaphores in Process Synchronization. 1 Binary Semaphore –. This is also known as mutex lock. It can have only two values – 0 and 1. Its value is initialized to 1. It is used to implement ... 2 Counting Semaphore –. Its value can range over an unrestricted domain. It is used to control access to a resource that has multiple instances.

What is Semaphore in C language?

In more words, semaphores are a technique for coordinating or synchronizing activities in which multiple processes compete for the same resources. There are 2 types of semaphores: Binary semaphores & Counting semaphores. But our focus would be on binary semaphore only. That too binary semaphore example between threads in C language specifically.

How to count semaphores in a process?

If you have multiple instances of the resource then counting semaphores can be used. Next, the process creates two threads. thread1 acquires the semaphore variable by calling sem_wait (). Next, it executes statements in its critical section part. We use sleep (1) function to preempt thread1 and start thread2.

Is there a binary semaphore between threads in C?

That too binary semaphore example between threads in C language specifically. If you are in search of semaphore between processes then see this. As its name suggest binary semaphore can have a value either 0 or 1.


1 Answers

May i suggest you to use System V semaphores? This is the code:

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

#include "Semaphores.h"

#define SEM1_KEY (key_t)888
#define SEM2_KEY (key_t)1234

int sem1, sem2;


int main()
{
    pid_t pid;

    sem1 = semget(SEM1_KEY, 1, IPC_CREAT | 0666);
    if(sem1 < 0)
    {
        fprintf(stderr, "\nSEMGET Failed\n");
        exit(EXIT_FAILURE);
    }

    sem2 = semget(SEM2_KEY, 1, IPC_CREAT | 0666);
    if(sem1 < 0)
    {
        fprintf(stderr, "\nSEMGET Failed\n");
        exit(EXIT_FAILURE);
    }

    SEM_SET(sem1, 1);
    SEM_SET(sem2, 0);

    if((pid = fork()) == -1)
    {
        fprintf(stderr, "\nError in fork()\n");
        exit(EXIT_FAILURE);
    }
    if(pid == 0)
    {
        while(1)
        {   
            SEM_WAIT(sem2);
            printf("%c", 'B');
            fflush(stdout);
            sleep(1);
            SEM_POST(sem1);
        }
    }

    while(1)
    {
        SEM_WAIT(sem1);
        printf("%c", 'A');
        fflush(stdout);
        sleep(1);
        SEM_POST(sem2);
    }

    wait(0);

    SEM_DEL(sem1);
    SEM_DEL(sem2);
    exit(EXIT_SUCCESS);
}

And this is the header file Semaphores.h which includes the System V semaphores implementation:

#include <sys/sem.h>


union semun
{
    int val;

    struct semid_ds * buf;

    unsigned short * array;

};


int SEM_SET(int sem_id, int sem_val)
{
    union semun sem_union;

    sem_union.val = sem_val;

    return semctl(sem_id, 0, SETVAL, sem_union);
}

int SEM_DEL(int sem_id)
{
    return semctl(sem_id, 0, IPC_RMID);
}

int SEM_WAIT(int sem_id)
{
    struct sembuf sem_buf;

    sem_buf.sem_num = 0;
    sem_buf.sem_op = -1;
    sem_buf.sem_flg = SEM_UNDO;
    return semop(sem_id, &sem_buf, 1);
}

int SEM_POST(int sem_id)
{
    struct sembuf sem_buf;

    sem_buf.sem_num = 0;
    sem_buf.sem_op = 1;
    sem_buf.sem_flg = SEM_UNDO;
    return semop(sem_id, &sem_buf, 1);
}

The result will be this:

ABABABABABABABABA and so on

fflush() was probably the problem, but your code has some leaks, you need to understand what is a critical section, and you need to check for the return values of fork().

like image 193
Stefano Raneri Avatar answered Oct 20 '22 09:10

Stefano Raneri