#include #include #include #include #include #include #include #define BUFLEN 512 int main( int argc, char ** argv ) { int iWait; int iRead; char buf [BUFLEN]; int childToParent[2],parentToChild[2]; if (pipe(childToParent) == -1) { perror("pipe failed"); //exit(1); return 1; } if (pipe(parentToChild) == -1) { perror("pipe failed"); //exit(1); return 1; } // The kernel does not distinguish between the two pipes. pid_t iWhich = fork (); if (iWhich < 0) { perror("fork failed"); //exit(2); return 1; } else if (iWhich == 0) { /*child process*/ printf ("Childish <%d>\n", iWhich); // The child inherits all open file descriptors, including the pipes. int toParent = childToParent[1]; // The writable end of one pipe. int fromParent = parentToChild[0]; // The readable end of the other. printf ("Child::childToParent <%d><%d><%d>\n", iWhich, childToParent[0], childToParent[1]); printf ("Child::parentToChild <%d><%d><%d>\n", iWhich, parentToChild[0], parentToChild[1]); close(childToParent[0]); close(parentToChild[1]); // Close the end of each pipe the child is not going to use. // This permits the kernel to correctly transmit end of file. // write(toParent,whatever,length_of_whatever); // read(fromParent,whatever,length_of_whatever); // The child or parent can also do an exec to run a separate program. The // open pipe file descriptors remain open through an exec, so if, for // example, toParent equals 17 after the fork, you can exec another program // and still write to file descriptor 17 and it will be sent to the parent. // In such cases, the usual practice is to rename the descriptors to // well-known descriptors such as 0 (for input) and 1 (for output) using dup, // dup2, etc. For example, if the child process is to execute "xyz" and // doesn't need the parent's stdin or stdout, // int fromParentDup = dup2(fromParent,0); /* turn the pipe from-parent into stdin. */ int toParentDup = dup2(toParent,1); /* turn the pipe to-parent into stdout. */ // the child process can then read and write its stdin and stdout and never know it is // actually communicating through a pipe to another process. printf ("Child still here ... <%d>\n", iWhich); execlp("more","more","main.cpp",NULL); flush(); // system ("more main.cpp"); exit (0); } else { /* parent process */ // sleep (5); printf ("Parental watch ... <%d>\n", iWhich); // Sort of the mirror image of what we did with the child. int fromChild = childToParent[0]; // The readable end of one pipe. int toChild = parentToChild[1]; // The writeable end of the other. printf ("Parent::childToParent <%d><%d><%d>\n", iWhich, childToParent[0], childToParent[1]); printf ("Parent::parentToChild <%d><%d><%d>\n", iWhich, parentToChild[0], parentToChild[1]); close(childToParent[1]); close(parentToChild[0]); // Close the end of each pipe the parent is not going to use. // This permits the kernel to correctly transmit end of file. printf ("Parental watch ... <%d>\n", iWhich); pid_t thePid = 0; while (read(fromChild,buf, BUFLEN)) { // while (thePid != iWhich) { sleep (1); read(fromChild,buf, BUFLEN); printf ("iWait !!!<%d> iWhich<%d>\n", iWait, iWhich); thePid = waitpid(iWhich, &iWait, WNOHANG); printf ("Parent:<%d> <%s>\n", (int)thePid, (char *)buf); } // write(toChild,whatever,length_of_whatever); // wait for child process to finish .. wait (&iWait); printf ("Parental EXIT !!!<%d><%d><%d>\n", iWait, thePid, iWhich); } return 0; }