602 Chapter 28
/* If argc > 1, child shares file descriptor table with parent */
e flags = (argc > 1)? CLONE_FILES : 0;
/* Allocate stack for child */
r stack = malloc(STACK_SIZE);
if (stack == NULL)
errExit("malloc");
stackTop = stack + STACK_SIZE; /* Assume stack grows downward */
/* Ignore CHILD_SIG, in case it is a signal whose default is to
terminate the process; but don't ignore SIGCHLD (which is ignored
by default), since that would prevent the creation of a zombie. */
t if (CHILD_SIG != 0 && CHILD_SIG != SIGCHLD)
if (signal(CHILD_SIG, SIG_IGN) == SIG_ERR)
errExit("signal");
/* Create child; child commences execution in childFunc() */
y if (clone(childFunc, stackTop, flags | CHILD_SIG, (void *) &fd) == -1)
errExit("clone");
/* Parent falls through to here. Wait for child; __WCLONE is
needed for child notifying with signal other than SIGCHLD. */
u if (waitpid(-1, NULL, (CHILD_SIG != SIGCHLD)? __WCLONE : 0) == -1)
errExit("waitpid");
printf("child has terminated\n");
/* Did close() of file descriptor in child affect parent? */
i s = write(fd, "x", 1);
if (s == -1 && errno == EBADF)
printf("file descriptor %d has been closed\n", fd);
else if (s == -1)
printf("write() on file descriptor %d failed "
"unexpectedly (%s)\n", fd, strerror(errno));
else
printf("write() on file descriptor %d succeeded\n", fd);
exit(EXIT_SUCCESS);
}
––––––––––––––––––––––––––––––––––––––––––––––––––– procexec/t_clone.c
When we run the program in Listing 28-3 without a command-line argument, we
see the following:
$ ./t_clone Doesn’t use CLONE_FILES
child has terminated
write() on file descriptor 3 succeeded Child’s close() did not affect parent