The purpose of this assignment is to become more familiar with the concepts of process control and signaling. You’ll do this by expanding your previously created simple Unix shell program
I have a new handout which you should then integrate your last shell into: lab1b-handout.tar
You are tasked with implementing a unix shell! This sounds intimidating but it's really not so bad.
Your shell must be able to:
bg <%jid|pid>
-- change a stopped background job to a running background jobkill <%jid|pid>
-- send SIGINT to the specified background jobjobs
-- list the running and stopped background jobsfg
should also now require a job id or process id as an argumentREMINDER: ONLY ONE JOB CAN RUN IN THE FOREGROUND AT A TIME
I'm providing a bit of additional code to help with job control by means of a jobctrl
library. The header file (public API) is included in this new tsh.c
skeleton code. DO NOT CHANGE jobctrl.c
IN ANY WAY
tsh> /bin/sleep 100 &
[1] (823) /bin/sleep 100 &
tsh> /bin/sleep 90 &
[2] (824) /bin/sleep 90 &
tsh> /bin/sleep 80 &
[3] (825) /bin/sleep 80 &
tsh> /bin/sleep 70 &
[4] (826) /bin/sleep 70 &
tsh> jobs
[1] (823) Running /bin/sleep 100 &
[2] (824) Running /bin/sleep 90 &
[3] (825) Running /bin/sleep 80 &
[4] (826) Running /bin/sleep 70 &
tsh> fg %1
tsh>
Job [1] (823) stopped by signal 20 <<<< Ctrl+Z pressed here
tsh> jobs
[1] (823) Stopped /bin/sleep 100 &
[2] (824) Running /bin/sleep 90 &
[3] (825) Running /bin/sleep 80 &
[4] (826) Running /bin/sleep 70 &
tsh> bg 999
999: No such pid
tsh> bg %5
%5: No such job
tsh> bg %1
tsh> jobs
[1] (823) Running /bin/sleep 100 &
[2] (824) Running /bin/sleep 90 &
[3] (825) Running /bin/sleep 80 &
[4] (826) Running /bin/sleep 70 &
tsh> kill %3
Job [3] (825) terminated by signal 2
tsh> jobs
[1] (823) Running /bin/sleep 100 &
[2] (824) Running /bin/sleep 90 &
[4] (826) Running /bin/sleep 70 &
tsh> fg 823
tsh>
Job [1] (823) terminated by signal 2 <<<< Ctrl+C pressed here
tsh> kill 826
Job [4] (826) terminated by signal 2
tsh> jobs
[2] (824) Running /bin/sleep 90 &
tsh>
ctrl-c
should cause a SIGINT
signal to be sent to the current foreground job as well as any descendents of the job. If there is no foreground job, then the signal should have no effectctrl-z
should cause a SIGTSTP
signal to be sent to the current foreground job as well as any descendents of the job. If there is no foreground job, then the signal should have no effect&
, then the new job should be run in the background. Otherwise, it should run the job in the foregroundquit
-- terminates the shelljobs
-- lists all jobs. HINT: jobctrl
has a function that might do exactly thatbg <job>
-- restarts <job>
by sending SIGCONT
and runs it in the background. The <job>
argument can be either a PID (pid
) or JID (%jid
)fg <job>
-- restarts <job>
by sending SIGCONT
and runs it in the forground. The <job>
argument can be either a PID (pid
) or JID (%jid
)kill <job>
-- interrupt <job>
by sending SIGINT
to the process group. The <job>
argument can be either a PID (pid
) or JID (%jid
)tsh
should recognize this event and print a message with the job's PID and a description of the offending signalYou are welcome to organize this in any way, but you may find it helpful to structure your code into the following methods:
eval
-- main routine that parses and interprets the command linebuiltin_cmd
-- recognize and interprets the built-in commandswaitfg
-- waits for a foreground job to completedo_bgfgkill
-- process the fg, bg, and kill built-inssigchld_handler
-- catches SIGCHILD signalssigint_handler
-- catches SIGINT (ctrl-c
) signalssigstp_handler
-- catches SIGTSTP (ctrl-z
) signalsI have made a reference solution available which will run on the linux lab machines tshref. You are welcome to compare functionality and output between your solution and mine
I also have a series of autograded tests when you submit on autolab
%
. For example, %5
denotes JID 5 while 5
denotes PID 5.waitfg
can be drastically simplified -- "while my foreground process ID is the same, suspend"TAKE ADVANTAGE OF THE CODE I ADDITIONALLY PROVIDE
Most importantly, start early.
Expand the kill
built-in command to accept an optional argument which specifies the signal to send (the default should be SIGINT -- or signal 2)
tsh> /bin/sleep 10 &
[1] (823) /bin/sleep 10 &
tsh> kill -9 %1
Job [1] (823) terminated by signal 9
You can view a list of signal numbers by looking at the man page for signal: man 3 signal
Upload/submit tsh.c
to autolab.
This lab will be graded out of 100 points.
85pt
-- autograded15pt
-- style, design, naming, formatting