12-Week Practicum Solutions Spring 2014
Problem 1
BIG IDEA Need to connect the different parts of the compilation
process up. First compile to object files using the -c option, and
then assemble object files into the binary exectuable. Don't forget
the -lreadline
flag.
#TODO: Complete the MAkefile to compile rpn # # NOTES: # (1) you must use clang as your compiler # (2) you must compile to .o object files and combine them into an executable # (3) you must have a clean to remove binary and .o files # (4) you MAY NOT use Makefile vairables, like CC or CFLAGS # # (hint: don't foget about adding in the readline library via -l) all: rpn # COMPLETE BLEOW rpn: mathlib.o rpn.o clang -lreadline mathlib.o rpn.o -o rpn mathlib.o: mathlib.c clang -c mathlib.c -o mathlib.o rpn.o: rpn.c clang -c rpn.c -o rpn.o clean: rm -f mathlib.o rpn.o *~ rpn
Problem 2
BIG IDEA: There exists a pipe between each process. Only the first
process the parent requires a dup onto stdout because cat
is
executed. All other process just use the pipe as is. The only further
requirement is that the pipeline is widowed.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/wait.h> int main(int argc, char *argv[]){ char * cmd[] = {"cat", NULL}; int cpid; int pfd_1[2] = {-1,-1},pfd_2[2] = {-1,-1}; char c; //TODO: add neccesary pipeline code pipe(pfd_1); if( (cpid = fork()) ) { /* CHILD 1 */ //TODO: add neccesary pipeline code pipe(pfd_2); if( (cpid = fork()) ) { /* CHILD 2*/ //TODO: add neccesary pipeline code close(pfd_2[1]); close(pfd_1[1]); //read from pfd_2 and write to stdout while(1){ if(read(pfd_2[0],&c,1)){ write(1,&c,1); }else{ exit(0); } } }else if(cpid == 0){ /* CHILD 1 */ //TODO: add neccesary pipeline code close(pfd_1[1]); close(pfd_2[0]); //read from pfd_1 and write to pfd_2 while(1){ if(read(pfd_1[0],&c,1)){ write(pfd_2[1],&c,1); }else{ exit(0); } } } }else if(cpid == 0){ /* PARENT */ close(1); //TODO: add neccesary pipeline code close(pfd_1[0]); dup2(pfd_1[1],1); //execute the cat command execvp(cmd[0], cmd); perror("exec failure"); _exit(1); } }
Problem 3
BIG IDEA: The pong
program must be able to handle any signal
numbered 1-32 and also know the pid of the process that sent it the
signal. This requires using sigaction()
with the SA_SIGINFO
flag
and also establishing the action with all signals.
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> //TODO: Complete the signal handler // // * The arguments to the signal handler function depend on the type // of handler, e.g., a basic handler or one that requires a // siginfo //void handler(/* setup arguments */){ void handler(int signum, siginfo_t * info, void * contenxt){ printf("pong %d\n", info->si_signo); kill(info->si_pid, info->si_signo); exit(0); //DO NOT EDIT } int main(int argc, char * argv[]){ //DO NOT EDIT pid_t cpid; //child pid char * cmd_ping[] = {"./ping", NULL}; //cmd_argv int i; //iterator /////////////////////// //TODO: Setup signal handler // // * Will need to handle potentiall all signals, except SIGCHLD, // SIGKILL, and SIGSTOP // // * Will probably need to use sigaction() insted of signal() to // establish the handler, may want siginfo data struct sigaction action; action.sa_sigaction=handler; action.sa_flags=SA_SIGINFO | SA_RESTART; //setup handler for all signals except SIGCHLD for(i = 0; i < 32; i++){ if ( i == SIGCHLD ) continue; sigaction(i, &action, NULL); } //DO NOT EDIT/////////////////////// if( (cpid = fork()) == 0 ){ /* CHILD */ execvp(cmd_ping[0], cmd_ping); perror("exec"); exit(2); }else{ /* PARENT */ wait(NULL); } return 0; ////////////////////////////////// }