Example 5-1 shows the basic procedures for executing an image in a child process.
The child process in Example 5-1 prints a message 10 times.
/* This example creates the child process. The only * * functionality given to the child is the ability to * * print a message 10 times. * * * * PARENT: */ #include <climsgdef.h> /* CLI status values */ #include <stdio.h> #include <perror.h> #include <processes.h> main() { int status, cstatus; if ((status = vfork()) != 0) { if (status < 0) printf("Parent - Child process failed\n"); else { printf("Parent - Waiting for Child\n"); if ((status = wait(&cstatus)) == -1) perror("Parent - Wait failed"); else if (cstatus == CLI$_IMAGEFNF) printf("Parent - Child does not \ exist\n"); else printf("Parent - Child final \ status: %d\n", cstatus); } } else { printf("Parent - Starting Child\n"); if ((status = execl("child", 0)) == -1) { perror("Parent - Execl failed"); _exit(); } } }
/* This is a program separate from the parent process. * * * * CHILD: * * */ main() { int i; for (i=0; i < 10; i++) printf("Child - executing\n"); }
Key to Example 5-1:
The vfork function is normally used in the expression of an if statement. This construct allows you to take advantage of the double return aspect of vfork, since one return value is 0 and the other is nonzero.
In Example 5-2, the parent passes arguments to the child process.
/* In this example, the arguments are placed in an array, * * gargv, but they can be passed to the child * * explicitly as a zero-terminated series of character * * strings. The child program in this example writes * * to stdout the arguments that have been passed to it. * * * * PARENT: * * */ #include <climsgdef.h> #include <stdio.h> #include <perror.h> #include <processes.h> main() { int status, cstatus; char *gargv[] = { "Child", "ARGC1", "ARGC2", "Parent", 0 }; if ((status = vfork()) != 0) { if (status < -1) printf("Parent - Child process failed\n"); else { printf("Parent - waiting for Child\n"); if ((status = wait(&cstatus)) == -1) perror("Parent - Wait failed"); else if (cstatus == CLI$_IMAGEFNF) printf("Parent - Child does not exist\n"); else printf("Parent - Child final status: %x\n", cstatus); } } else { printf("Parent - Starting Child\n"); if ((status = execv("Child", gargv)) == -1) { perror("Parent - Exec failed"); _exit(); } } } /* This is a program separate from the parent process. * * * * CHILD: * * */ main(argc, argv) int argc; char *argv[]; { int i; printf("Program name: %s\n", argv[0]); for (i = 1; i < argc; i++) printf("Argument %d: %s\n", i, argv[i]); }
Example 5-3 shows how to use the wait function to check the final status of multiple children being run simultaneously.
/* In this example, the wait function is placed in a separate * * for loop so that it is called once for each child. If * * wait were called within the first for loop, the parent * * would wait for one child to terminate before executing the * * next child. If there were only one wait request, any * * child still running when the parent exits would terminate * * prematurely. * * * * PARENT: * * */ #include <climsgdef.h> #include <stdio.h> #include <perror.h> #include <processes.h> main() { int status, cstatus, i; for (i = 0; i < 5; i++) { if ((status = vfork()) == 0) { printf("Parent - Starting Child %d\n", i); if ((status = execl("child", 0)) == -1) { perror("Parent - Exec failed"); _exit(); } } else if (status < -1) printf("Parent - Child process failed\n"); } printf("Parent - Waiting for children\n"); for (i = 0; i < 5; i++) { if ((status = wait(&cstatus)) == -1) perror("Parent - Wait failed"); else if (cstatus == CLI$_IMAGEFNF) printf("Parent - Child does not exist\n"); else printf("Parent - Child %X final status: %d\n", status, cstatus); } } /* This is a program separate from the parent process. * * * * CHILD: * * */ main() { int pid, i; printf("Child %0X: working...\n", (pid = getpid())); sleep(5); printf("Child %0X: Finished\n",pid); }
Example 5-4 shows how to use the pipe and dup2 functions to communicate between a parent and child process through specific file descriptors. The #define preprocessor directive defines the preprocessor constants inpipe and outpipe as the names of file descriptors 11 and 12.
/* In this example, the parent writes a string to the pipe * * for the child to read. The child then writes the string * * back to the pipe for the parent to read. The wait * * function is called before the parent reads the string that * * the child has passed back through the pipe. Otherwise, * * the reads and writes will not be synchronized. * * * * PARENT: * * */ #include <perror.h> #include <climsgdef.h> #include <stdio.h> #include <processes.h> #include <unixio.h> #define inpipe 11 #define outpipe 12 main() { int pipes[2]; int mode, status, cstatus, len; char *outbuf, *inbuf; if ((outbuf = malloc(512)) == 0) { printf("Parent - Outbuf allocation failed\n"); exit(); } if ((inbuf = malloc(512)) == 0) { printf("Parent - Inbuf allocation failed\n"); exit(); } if (pipe(pipes) == -1) { printf("Parent - Pipe allocation failed\n"); exit(); } dup2(pipes[0], inpipe); dup2(pipes[1], outpipe); strcpy(outbuf, "This is a test of two-way pipes.\n"); status = vfork(); switch (status) { case 0: printf("Parent - Starting child\n"); if ((status = execl("child", 0)) == -1) { printf("Parent - Exec failed"); _exit(); } break; case -1: printf("Parent - Child process failed\n"); break; default: printf("Parent - Writing to child\n"); if (write(outpipe, outbuf, strlen(outbuf)+1) == -1) { perror("Parent - Write failed"); exit(); } else { if ((status = wait(&cstatus)) == -1) perror("Parent - Wait failed"); if (cstatus == CLI$_IMAGEFNF) printf("Parent - Child does not exist\n"); else { printf("Parent - Reading from child\n"); if ((len = read(inpipe, inbuf, 512)) <= 0) { perror("Parent - Read failed"); exit(); } else { printf("Parent: %s\n", inbuf); printf("Parent - Child final \ status: %d\n", cstatus); } } } break; } } /* This is a program separate from the parent process. * * * * CHILD: * * */ #define inpipe 11 #define outpipe 12 main() { char *buffer; int len; if ((buffer = malloc(512)) == 0) { perror("Child - Buffer allocation failed\n"); exit(); } printf("Child - Reading from parent\n"); if ((len = read(inpipe, buffer, 512)) <=0) { perror("Child - Read failed"); exit(); } else { printf("Child: %s\n", buffer); printf("Child - Writing to parent\n"); if (write(outpipe, buffer, strlen(buffer)+1) == -1) { perror("Child - Write failed"); exit(); } } }