Synchronizing two child processes with semaphores in c

Viewed 2176

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

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().

Related