I'm trying to implement some IPC without mutex's,conditions and semaphores, only using pipes.
The following code represents a parent process forking in 3 childs (p11,p12,p13)
the parent wakes up all the childs with a SIGUSR2
signal,then p11 starts writing 50 random numbers to the pipe. p12 and p13 competitively read from the pipe and write the numbers they get to their own file (file12 and file13). The 50th number is a -1
, once the childs read -1, they exit.
The write
used in the p11 child, just doesn't write a single byte, it returns -1
I can only use write(2)
and read(2)
calls for writing and reading.
I can't seem to be able to implement it, I tried several times with no results. Hope you can help me.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/wait.h>
void handler(int signo)
{
printf("\nSignal intercepted!\n");
}
void main ()
{
srand(time(NULL));
signal(SIGUSR2,handler);
int pa[2];
pipe(pa[2]); //create pipe
pid_t pid1,pid2,pid3;
if((pid1=fork())==0) //child 11
{
close(pa[0]); //close the read side of the pipe
pause();
int i,nwrite,num;
for(i=0;i<49;i++)
{
num=rand()%100+1; //generate a random number
nwrite=write(pa[1],&num,sizeof(int)); //write it to the pipe
if(nwrite==-1) //if there's a write error
{
printf("\nWrite error..\n");
exit(-1);
}
}
num=-1; //generate the last number
nwrite=(write(pa[1],&num,sizeof(int))); //write the last number to the pipe
if (nwrite==-1) //if there's a write error
{
printf("\nError,now exiting...\n");
exit(-1);
}
close(pa[1]); //close the pipe in write mode
exit(1);
}
else if ((pid2=fork())==0) //child 12
{
close(pa[1]); //close the write side of the pipe
pause();
int fd1,nread,num;
fd1=open("file12.txt",O_CREAT,0777); //create a new file
while((nread=read(pa[0],&num,sizeof(num)))>0) //while there are bytes to read
{
if(num!=-1) //if this isn't the last number
{
write(fd1,&num,sizeof(num)); //write it to the file
}
else
{
printf("\n-1 sent!\n"); //notify the last read number
close(pa[0]); //close the read side of the pipe
close(fd1); //close the file descriptor
exit(1); //exit
}
}
}
else if ((pid3=fork())==0) //child 13, same as 12
{
close(pa[1]);
pause();
int fd2,nread,num;
fd2=open("file13.txt",O_CREAT,0777);
while((nread=read(pa[0],&num,sizeof(num)))>0)
{
if(num!=-1)
{
write(fd2,&num,sizeof(num));
}
else
{
printf("\n-1 sent!\n");
close(pa[0]);
close(fd2);
exit(1);
}
}
}
else //parent
{
sleep(1);
kill(pid1,SIGUSR2); //wake up all the childs
kill(pid2,SIGUSR2);
kill(pid3,SIGUSR2);
waitpid(pid1,0,NULL); //wait for the childs to end
waitpid(pid2,0,NULL);
waitpid(pid3,0,NULL);
printf("\nDone, now exiting...\n"); //exit
}
}
At least this*1
int pa[2];
pipe(pa[2]);
should be
int pa[2];
pipe(pa);
Background:
pa[2]
evaluates to int
. pipe()
on the other hand expects a int[2]
, which in the context of defining a function's parameter is the same as int[]
which is the same as int *
.
If an array gets passed to a function it decays to a pointer its 1st element. So passing pa
to pipe()
would result in passing &pa[0]
, which indeed is an int *
.
*1
BTW, coding pa[2]
provokes undefined behaviour in any case as it reads out the 3rd element of pa
, with pa
only having two elements.