Reputation: 105
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
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