//------------------------------------------------------------------- // pipedemo.cpp // // This program illustrates use of asynchronous notification to // signal a parent-process that some new data from its child is // now ready to be read from one of its open input-pipes. // // programmer: ALLAN CRUSE // written on: 27 APR 2005 //------------------------------------------------------------------- #include // for printf(), perror() #include // for open() #include // for exit() #include // for read(), write(), close() #include // for sigaction() #include // for strlen() #include // for fcntl() int done = 0; void my_sigaction( int signo, siginfo_t *info, void *data ) { if ( signo == SIGCHLD ) done = 1; else if ( signo != SIGUSR1 ) return; char inbuf[ 128 ] = {0}; int nbytes = read( info->si_fd, inbuf, sizeof( inbuf )-1 ); if ( nbytes < 0 ) return; if ( !done ) printf( "received from %d: %s \n", info->si_fd, inbuf ); } int main( int argc, char **argv ) { // create the pair of pipes and the child-process int fd1[2], fd2[2]; pipe( fd1 ); pipe( fd2 ); int pid = fork(); if ( pid == 0 ) { // this is the child process close( fd1[0] ); close( fd2[0] ); sleep( 2 ); char msg1[] = " Hello "; write( fd1[1], msg1, strlen( msg1 ) ); sleep( 1 ); write( fd2[1], msg1, strlen( msg1 ) ); sleep( 1 ); char msg2[] = " Goodbye "; write( fd1[1], msg2, strlen( msg2 ) ); sleep( 1 ); write( fd2[1], msg2, strlen( msg2 ) ); sleep( 1 ); exit( 0 ); } // this is the parent-process close( fd1[1] ); close( fd2[1] ); // install signal-handler for SIGUSR1 struct sigaction oa, sa = {0}; sigemptyset( &sa.sa_mask ); sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = my_sigaction; sigaction( SIGUSR1, &sa, &oa ); sigaction( SIGCHLD, &sa, &oa ); // specify that parent-process receives the notifications fcntl( fd1[0], F_SETOWN, getpid() ); fcntl( fd2[0], F_SETOWN, getpid() ); // enable anynchronous notification for these input-pipes fcntl( fd1[0], F_SETFL, fcntl( fd1[0], F_GETFL )|FASYNC ); fcntl( fd2[0], F_SETFL, fcntl( fd2[0], F_GETFL )|FASYNC ); // specify the signal-number for the input-notifications fcntl( fd1[0], F_SETSIG, SIGUSR1 ); fcntl( fd2[0], F_SETSIG, SIGUSR1 ); // main loop to wait for the SIGCHLD signal while ( !done ) pause(); // restore the original signal-handler for SIGUSR1 and quit sigaction( SIGUSR1, &oa, NULL ); printf( "now parent is quitting\n" ); exit( 0 ); }