#include #include #include #include #include #include /* function prototypes */ int child(); void parent( int children, int childpids[] ); int main() { int i, children = 8; /* based on a true story..... */ int childpids[8]; /* srand( time( NULL ) ); */ for ( i = 0 ; i < children ; i++ ) { pid_t z = fork(); if ( z < 0 ) { fprintf( stderr, "ERROR: fork() failed.\n" ); exit( 1 ); } if ( z == 0 ) { int rc = child(); exit( rc ); } childpids[i] = z; /* save each child pid in the parent process */ } parent( children, childpids ); return 0; } void * handle_sigint( int n ) { printf( "CHILD: Caught SIGINT (%d). Okay, I'm awake!\n", n ); return (void *)NULL; } int child() { int t; printf( "CHILD: I'm new. My pid is %d.\n", getpid() ); signal( SIGINT, (void *)handle_sigint ); /* srand( time( NULL ) ); */ srand( time( NULL ) * getpid() * getpid() ); t = 10 + ( rand() % 21 ); /* [10,30] */ printf( "CHILD: I'm gonna nap for %d seconds\n", t ); t -= sleep( t ); /* man 3 sleep */ return t; } void parent( int children, int childpids[] ) { int status; /* return status from a child */ pid_t child_pid; printf( "PARENT: I'm waiting for children.\n" ); while ( children > 0 ) { #if 0 /* wait until a child process exits */ child_pid = wait( &status ); /* BLOCKS */ #endif /* check to see if a child has terminated (without blocking) */ child_pid = waitpid( 0, &status, WNOHANG ); /* or -1 for first arg */ if ( child_pid == 0 ) { if ( children > 4 ) { printf( "PARENT: I'm still waiting. I'll take a nap.\n" ); sleep( 3 ); } else { printf( "PARENT: I'm tired of waiting!\n" ); int j; for ( j = 0 ; j < 8 ; j++ ) { kill( childpids[j], SIGINT ); /* see man 7 signal */ /* should also check the return value of kill() */ /* * this sends a SIGINT (or SIGKILL) to each child process, even if they've already terminated (so not all signals will reach a process) */ } sleep( 2 ); } } else /* assume child_pid > 0 should also check for error! */ { children--; printf( "PARENT: child process %d exited...", child_pid ); if ( WIFSIGNALED( status ) ) /* e.g. core dump */ { printf( "...abnormally\n" ); } else if ( WIFEXITED( status ) ) { int rc = WEXITSTATUS( status ); printf( "...after sleeping %d seconds\n", rc ); } printf( "PARENT: %d more to go\n", children ); } } printf( "PARENT: All done.\n" ); }