Best代写-最专业靠谱代写IT | CS | 留学生作业 | 编程代写Java | Python |C/C++ | PHP | Matlab | Assignment Project Homework代写

C语言代写Linux Shell | 15-213/18-213/15-513 Shell Lab

C语言代写Linux Shell | 15-213/18-213/15-513 Shell Lab

本次北美CS代写主要是C代写代写Linux shell 脚本程序

15-213/18-213/15-513, Fall 2020 Shell Lab: Writing Your Own Linux Shell

Assigned: Thurs, April 8, 2021
Due: Thurs, April 22, 2021 at 11:59 PM
Last Possible Handin: Sunday, April 25, 2021 at 11:59 PM

1 Introduction

The purpose of this assignment is to help you become more familiar with the concepts of process control and signalling. You’ll do this by writing a simple Linux shell program, tsh (tiny shell), that supports a simple form of job control and I/O redirection. Please read the whole writeup before starting.

2 Logistics

This is an individual project. All handins are electronic. You must do this lab assignment on a class shark machine.

To get your lab materials, click ”Download Handout” on Autolab. Clone your repository on a Shark machine by running:

linux> git clone<USERNAME>.git 3 Overview

Looking at the tsh.c file, you will see that it contains a skeleton of a simple Linux shell. It will not, of course, function as a shell if you compile and run it now. To help you get started, we’ve provided you with a helper file, tsh helper.{c,h}, which contains the implementation of routines that manipulate a job list, and a command line parser. Read the header file carefully to understand how to use it in your shell.

Your assignment is to complete the remaining empty functions listed below.

• eval: Main routine that parses, interprets, and executes the command line. • sigchld handler: Handles SIGCHLD signals.
• sigint handler: Handles SIGINT signals (sent by Ctrl-C).
• sigtstp handler: Handles SIGTSTP signals (sent by Ctrl-Z).


When you wish to test your shell, type make to recompile it. To run it, type tsh to the command line:

linux> ./tsh
tsh> [type commands to your shell here]

4 General Guidelines for Writing Your Shell

This section provides an overview of how you can start writing your shell. You should read Section 4: The tsh Specification, for a list of everything your shell should support and the format of all shell output.

  • A shell is an interactive command-line interpreter that runs programs on behalf of the user. A shell repeatedly prints a prompt, waits for a command line on stdin, and then carries out some action, as directed by the contents of the command line.

    Each command consists of one or more words, the first of which is the name of an action to perform. This may either be the path to an executable file (e.g., tsh> /bin/ls), or a built- in command—a word with special meaning to the shell—(e.g., tsh> quit). Following this are command-line arguments to be passed to the command.

  • Built-in commands run within the shell’s process. Looking at the handout code, you may notice that it’s difficult to exit the program. Try making it respond to the word quit.
  • So as not to corrupt its own state, the shell runs each executable in its own child process. You should recall from lecture the sequence of three library calls necessary to create a new process, run a particular executable, and wait for a child process to end. Try to make your shell correctly respond to /bin/ls, without breaking the existing quit command. If this works, try passing ls a particular directory to make sure your shell is passing the arguments along.
  • The child processes created as a result of interpreting a single command line are known collectively as a job. We just saw one type of job, a foreground job. However, sometimes a user wants to do more than one thing at once: in this case, they can instruct the shell not to wait for a command to terminate by instead running it as a background job. Looking back at the sequence of calls you made to implement foreground jobs, what do you think you would do differently to spawn a background job?
  • Given that your shell will need to support both types of job, consider refactoring your existing code to minimize the amount of duplication that will be necessary.
  • Try implementing the execution of background jobs, which your shell should do when- ever the command line ends with an & character. To test this feature, try executing tsh> /usr/bin/sleep 5 and comparing against tsh> /usr/bin/sleep 5 &. In the latter case, the command prompt should appear immediately after running the command. Now you can run multiple sleeps at once!
  • When children of your shell die, they must be reaped within a bounded amount of time. This means that you should not wait for a running foreground process to finish or for a user input to be entered before reaping. The sigchld handler might be a good place to reap all your child processes.


  • The shell might want to track in-flight jobs and provide an interface for switching their status i.e. background to foreground, etc. Now might be a good time to read the api in tsh helper.{c,h} and start maintaining a job list.
  • Typing Ctrl-C or Ctrl-Z causes a SIGINT or SIGTSTP signal, respectively. Your shell should catch the signals and forward them to the entire process group that contains the foreground job. If there is no foreground job, then these signals should have no effect.
  • When you run your shell from the standard Linux shell, your shell is running in the foreground process group. If your shell then creates a child process, by default that child will also be a member of the foreground process group. Since typing Ctrl-C sends a SIGINT to every process in the foreground group, typing Ctrl-C will send a SIGINT to your shell, as well as to every process created by your shell. Obviously, this isn’t correct.

    Here is a possible workaround: After the fork, but before the execve, you may want to think of a way to put the child in a new process group whose group ID is identical to the child’s PID. This would ensure that there will be only one process, your shell, in the foreground process group. Hint: man setpgid. 1

  • Remember that signal handlers run concurrently with the program and can interrupt it any- where, unless you explicitly block the receipt of the signals. Be very careful about race conditions on the job list. To avoid race conditions, you should block any signals that might cause a signal handler to run any time you access or modify the job list.

    Aside from these guidelines, you should use the trace files to guide the development of your shell. The trace files are in order of difficulty so it might not be the best to attempt a trace before passing all traces up to it.

5 The tsh Specification
Your tsh shell should have the following features:

  • Each job can be identified by either a process ID (PID) or a job ID (JID). The latter is a positive integer assigned by tsh. JIDs are denoted on the command line with the prefix “%”. For example, “%5” denotes a JID of 5, and “5” denotes a PID of 5.
  • tsh should support the following built-in commands:
    • –  The quit command terminates the shell.
    • –  The jobs command lists all background jobs.
    • –  The bg job command resumes job by sending it a SIGCONT signal, and then runs it in the background. The job argument can be either a PID or a JID.
    • –  The fg job command resumes job by sending it a SIGCONT signal, and then runs it in the foreground. The job argument can be either a PID or a JID.