br33f
br33f

Reputation: 105

C - IPC semaphores with fork

I'm having a problem with following program:

What it was supposed to do: First child process should get a number from STDIN and set it to shared variable. Second child process should read number from shared variable and print it binary on STDOUT.

What it does: It never asks for a number, after running it, it just prints inifnite number of zero's. It looks like it jumps straight away into a second child and never leaves it.

Code:

   #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
/* jest zdefiniowane w sys/sem.h */
#else
union semun
{
    int val;
    struct semid_ds* buf;
    unsigned short int* array;
    struct seminfo* __buf;
};
#endif

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <fcntl.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/mman.h>

//shared
static int *glob_var;

struct sembuf operacja;

void operacjaSem(int, int, int);

int main(void)
{
    /*---------------------------------------*/
    //shared memory
    glob_var = mmap(NULL, sizeof(*glob_var), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);

    /*---------------------------------------*/
    //semafory
    key_t klucz;
    int semafor;
    union semun ustaw;

    //tworze jednoznaczny klucz dla semaforow
    if((klucz = ftok(".", 'B')) == -1)
    {
        fprintf(stderr, "blad tworzenia klucza\\n");
        exit(1);
    }

    //stworzenie semaforow
    if((semafor = semget(klucz, 2, IPC_CREAT | IPC_EXCL | 0600)) == -1)
    {
        fprintf(stderr, "blad tworzenia semaforow\\n");
        exit(1);
    }

    //inicjacja semaforow
    ustaw.val = 1;
    if(semctl(semafor, 0, SETVAL, ustaw) == -1)
    {
        fprintf(stderr, "blad ustawienia semafora0\\n");
        exit(1);
    }
    ustaw.val = 0;
    if(semctl(semafor, 1, SETVAL, ustaw) == -1)
    {
        fprintf(stderr, "blad ustawienia semafora1\\n");
        exit(1);
    }


    if(fork() == 0)
    {
        //first child process
        while(1)
        {
            if(semctl(semafor, 0, GETVAL) == 1)
            {
                //ustawiam zmienna wspoldzielona
                char buf2[128];
                fgets(buf2, 128, 0);
                *glob_var = atoi(buf2);
                //printf("buf: %d", *glob_var);
                //przestawiam semafory
                operacjaSem(semafor, 0, -1);
                operacjaSem(semafor, 1, 1);
            }

        }
    }
    if(fork() == 0)
    {
        //second child process
        while(1)
        {
            if(semctl(semafor, 1, GETVAL) == 1)
            {
                operacjaSem(semafor, 1, -1);
                //odczytuje i wypisuje
                int x = *glob_var;
                int p[32];
                for(int z = 0; z < 32; z++)
                {
                    if(x % 2 == 1 || x % 2 == -1) p[z] = 1;
                    else p[z] = 0;
                    x = x >> 1;
                }
                for(int z = 31; z >= 0; z--)
                    printf("%d", p[z]);
                printf("\n");

                //przestawiam semafory
                operacjaSem(semafor, 1, -1);
                operacjaSem(semafor, 0, 1);
            }
        }
    }
    return 0;
}

void operacjaSem(int semafor, int nr, int op)
{
    operacja.sem_num = nr;
    operacja.sem_op = op;
    operacja.sem_flg = 0;

    if(semop(semafor, &operacja, 1) == -1)
    {
        fprintf(stderr, "blad operacji na semaforze\\n");
        exit(1);
    }
}

Upvotes: 1

Views: 369

Answers (1)

Jorge Torres
Jorge Torres

Reputation: 1466

Change the first line that reads:

if(fork() == 0)

To something like

pid_t processID = fork();
if(processID == 0)

Change the second line that reads

if(fork() == 0)

To an else. More explicitly, for that second line, change:

}
if(fork() == 0)
{
    //second child process

To:

}
else
{
    if (processID < 0) {
        printf ("Fork error\n"); exit(-1);
    } 
    //second child process

And probably if the rest of your code is OK, it will start working. At least this will get your forks in good shape so you can keep working with the rest of the code.

Upvotes: 1

Related Questions