To initiate a new process, first `fork' to produce a duplicate of the current process.
int pid; /* process identifier */ pid = fork(); if ( pid < 0 ) { ... error, exit ... } if ( pid == 0 ) { ... child ... } else { ... parent, pid is child's pid ... }
A typical child might be
exec( program ); /* overlay with new program */
A typical parent might be
wait(); /* wait for child to finish */
execl( "/bin/pr", "pr", "-2", "file", 0 ); /* execl = long version */ execv( "/bin/pr", argv ); /* see 6.3.1 ? */ /* execv = argv type version */ execve( "/bin/pr", argv, arge ); /* exec?e = exec woth environment */ execlp( "pr", "pr", "-2", "file", 0 ); /* exec?p = exec with path */
The value of the firs argument in execl or of argv[0] in execv is entirely up to you.
exec calls do not return. They are therefore typically followed by code such as
execl( ... ); fprintf( stderr, "Error exec failed\n" ); exit( 1 );
wait returns the pid (numeric process identifier) of the dying process:
int i; .... pid = wait( &i );
If you give a parameter (`int *'), wait will return the process's exit status in i.
int p1, p2; p1 = fork(); if ( p1 == 0 ) { ... exec child1 ... ... printf error ... ... exit( 1 ); } p2 = fork(); if ( p2 == 0 ) { ... exec child2 ... ... error etc ... }
p = wait(); if ( p == p1 ) { ... first child died ... } if ( p == p2 ) { ... second child died ... }
A pipe is a one way input/out channel, which must be opened BEFORE the second process is forked off.
The argument to pipe is the name of an array of int variable of length two. Variable subscript [0] is the read end ( stdin is stream 0) and variable subscript [1] the write end ( stdout is stream 1).
int pdes[2]; int pid; pipe( pdes ); pid = fork(); if ( pid < 0 ) { .... error .... exit .... } if ( pid == 0 ) { /* child process */ /* child reads, doesn't write */ close( pdes[1] ); read( pdes[0], .... ); } else { /* parent process */ /* parent writes, doesn't read */ close( pdes[0] ); write( pdes[1], ... ); }
if ( fork() == 0 ) { /* child */ close( pdes[0] ); close( 1 ); dup( pdes[1] ); close( pdes[1] ); exec( childprog ... ) ... error exit etc ... } /* else parent */ close( pdes[1] ); read( pdes[0], ... );
This cannot be done with stdio.
int pc[2], /* parent to child */ cp[2]; /* child to parent */ /* open both pipes */ pipe( pc ); pipe( cp ); /* child code */ { close ( cp[0] ); close( pc[1] ); ... read pc[0], write to cp[1] ... } /* parent code */ { close( cp[1] ); close( pc[0] ); ... read cp[0], write to pc[1] ... }
We need two facilities: one to send a signal to another process (different signals, numbered 0 to 15, are possible), and another to say (early in a program) "if signal number so-and-so is received, do this".
#include <signal.h>
defines mnemonics for signals.
To send to given process a given signal
kill( pid, signalno ); kill( pid, SIGINT ); kill( pid, SIGALRM );
A library function to send a signal SIGALRM to the current process in 60 seconds permits you to write
alarm( 60 );
You must trap the signal (see below).
On receipt of the numbered signal, we require that a particular function `sigproc' is executed.
Use the format
sigproc() { ... to be executed on receipt of signal ... } main() { ... signal( signalno, sigproc ); ... }
signal delivers as its result a pointer to the trap function previously associated with this signal.
signal( signo, 0 ); /* to reset to previous sigproc */
newproc() { ... the new procedure } int (*oldproc)(); oldproc= signal( SIGINT, newproc ); /* signal delivers pointer to old proc */ /* when you are ready */ signal( SIGINT, oldproc ); /* reset old proc */
To control interrupts so that, for example in a menu driven system, an interrupt brings you back to the menu, we need jumps (goto's!) back to the start of the loop if an interrupt occurs.
#include "signal.h" #include "setjmp.h" jmp_buf inttrap; settrap() { signal( SIGINT, settrap ); signal( SIGQUIT, settrap ); next_prompt( "Type ? for help" ); longjmp( inttrap, 1 ); } main() ... while ( setjmp( inttrap ), ..., 1 ) { signal( SIGINT, settrap ); signal( SIGQUIT, settrap ); ... }
Copyright Eric Foxley 1996
Notes converted from troff to HTML by an Eric Foxley shell script, email errors to me!