I am learning process managing in Linux and I need to make child and parent communicate though a pipe. I have declared two structures:
typedef struct
{
double min, max, avg; /*Number stats*/
} Stats;
typedef struct {
pid_t pid; /*Process ID*/
int first; /*First number to process*/
int last; /*Last number to process*/
int fd[2]; /*Pipe descriptor*/
Stats stats; /*Stats computed by process*/
}Process_list;
I need the M child processes to compute some stats out of an array of numbers (dividing the work). Then, the child process would read the Process_list structure, process the numbers in the array from first to last (specified there) and save the computed stats into the stats structure.
The most relevant parts to my trouble of the code are the following (I am adding comments instead of other pieces of code to explain what is done OK):
int main(int argc, char *argv[])
{
pList=(Process_list *)malloc((M+1)*sizeof(Process_list));
/*Correct allocation is checked*/
int i;
pid_t pid;
for (i=0 ; i<M ; i++) /*M clones*/
{
/*Fork and pipe creation*/
pid = fork ();
pipe(pList[i].fd);
/*If it's the child*/
if ( pid == 0 )
{
pList[i].pid=pid;
printf("CHILD %d: %d a %d\n",i, pList[i].first,pList[i].last);
/*A function here computes stats and saves them OK in the struct*/
/*(e.g. min is saved in pList[i].stats.max, when printed it's a reasonable value)*/
/*Now I need to send the info to the parent*/
ret1=close(pList[i].fd[0]);
/*ret1=0 => OK */
ret2=write(pList[i].fd[1], &(pList[i].stats), sizeof(Stats));
printf("return write: %d\n",ret2);
/*TROUBLE HERE! This isn't even printed. sizeof(Stats)=24 which I think is OK*/
exit(EXIT_SUCCESS);
}
/*Parent*/
else if ( pid > 0 )
{
wait(NULL); /*Is this really neccesary?*/
ret1=close(pList[i].fd[1]);
ret2=read(pList[i].fd[0], &(pList[i].stats), sizeof(Stats));
/*Both ret1 and ret2 = 0*/
printf("[p]Mín: %lf\n Max: %lf\nAverage: %lf\n",pList[i].stats.min,pList[i].stats.max,pList[i].stats.avg);
/*Everything printed here = 0.0000000000*/
}
else /*fork error*/
return -1;
}
So my problem is that childs compute their stats perfectly, but the parent doesn’t receive them. The write() function does nothing. This happens for every value of M (including M=1 -just one process).
Also I don’t know if wait(NULL) is necessary, as I’ve seen some working examples that doesn’t use it. However, if I don’t write it there, the parent’s printfs will appear before the child’s, so I think it just doesn’t wait for the child to write in the pipe. It doesn’t work without it, anyway.
Or maybe the structure approach is just not a good one?
Thank you very much in advance!
You have to create the pipe before you fork it. Otherwise you are creating two pipes. One on your parent and one on your child which are not connected.
And
waitfor the child after you got all the data, else you may end up waiting forever if the child is blocking onwritefor the pipe buffer to clear.waitfrees up resources associated with a dead child. If your child is not dead this will wait until it is.Another thing: use
fwritefor writing blocks of data (arrays of structs) to a file descriptor.freadfor reading. You can convert a file descriptor to aFILE*withfdopen.