Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Project02 Shell History and Process Status (10%)

Deliverables due Wed Apr 9 by 11:59pm in your project02 GitHub repo

  • A copy of xv6 with your modified implementation of sh with history support
  • Your implementation should pass all of the Project02 Autograder tests.
  • Your source code should conform to xv6 formatting conventions.
  • Your Project02 repo should not have any extraneous files or build artifacts
  • Make sure to test your repo by cloning from GitHub to a different location and run the Autograder. This will catch problems like missing files.

Contents

  1. Overview
  2. History
  3. Free Kernel Memory
  4. Pipe Count
  5. Process Status

Overview

You will work on modifications to the xv6 shell, add new system calls, and add a new process status command.

Shell History

Shell command line history is a very useful feature. The xv6 shell (sh.c) does not currently support command line history. Your job in this project is to add command line history.

You will support the following shell built in commands for history:

history
!<text>
!<num>

The history builtin will list the history of commands:

$ echo hi
hi
$ echo bye
bye
$ history
    1  echo hi
    2  echo bye
    3  history
$ echo foo
foo
$ history
    1  echo hi
    2  echo bye
    3  history
    4  echo foo
    5  history
$ !2
echo bye
bye
$ history
    1  echo hi
    2  echo bye
    3  history
    4  echo foo
    5  history
    6  echo bye
    7  history
$ !5
history
    1  echo hi
    2  echo bye
    3  history
    4  echo foo
    5  history
    6  echo bye
    7  history
    8  history
$
$
$ history
    1  echo hi
    2  echo bye
    3  history
    4  echo foo
    5  history
    6  echo bye
    7  history
    8  history
    9  history
$ !ec
echo bye
bye
$ echo foo
foo
$ wc README
$ grep ACK README
$ history
    5  history
    6  echo bye
    7  history
    8  history
    9  history
   10  echo bye
   11  echo foo
   12  wc README
   13  grep ACK README
   14  history
$ !4
-sh: !4: event not found
$ !baz
-sh: !baz: event not found
$ foobar
exec foobar failed
$ history
    7  history
    8  history
    9  history
   10  echo bye
   11  echo foo
   12  wc README
   13  grep ACK README
   14  history
   15  foobar
   16  history
$

Implementation

For your implementation you should use the linked list implementation (list.c) to save the history. You should only store the 10 most recent commands. You can add your code directly to user/sh.c, but keep your code together in one location. Project02 will not be interactively graded, but we will review your code for quality.

Free Kernel Memory

Add a system call to xv6 called kmem(void) that returns the total number of free kernel pages. Also write a user-level program called kmem that will print the available amount of kernel memory in bytes.

xv6 kernel is booting

init: starting sh
$ kmem
Free kernel memory: 32529 pages (133238784 bytes)
$ 

Pipe Count

Add a system call to xv6 called pipect(int fd) that returns the number of bytes available in the pipe assuming fd is a file descriptor that is mapped to the read end of a pipe. If fd is not mapped to a pipe or not a valid file descriptor, return 0. Add a user-level program called pipect that will count the number of bytes on stdin assuming that it is a pipe:

$ echo foo | pipect
4

The count is 4 because echo adds a newline \n character.

Process Status

You can list the current xv6 process by typing CTRL-p. We are going to add a new user command called ps that will also show the list of processes, which will be like the ps command found in Linux.

$ ps
PID     STATE   SIZE    NAME
1       sleep   20480   init
2       sleep   24576   sh
4       run     24576   ps
$
$ busymany 100 5
$ ps
PID     STATE   SIZE    NAME
1       sleep   20480   init
2       sleep   24576   sh
11      run     24576   ps
6       sleep   24576   busy[A]
7       sleep   24576   busy[B]
8       sleep   24576   busy[C]
9       sleep   24576   busy[D]
10      sleep   24576   busy[E]
$ 

Requirements

  1. Add a new system call getprocs() that will copy elements of all the proc structs in the proc array to the user level
  2. The elements to be copied include: pid, name, status, sz
  3. Implement the getprocs() system call in kernel/proc.c
  4. Create a shared struct definition in kernel/getproc.h
  5. Create a new user program ps.c that will call getprocs() and display process information

Implementation Steps

1. Create the Shared Data Structure

Create kernel/getproc.h to define the shared structure that will be used to pass process information from kernel to user space:

// kernel/getproc.h
#ifndef GETPROC_H
#define GETPROC_H

// Process states
enum procstate { UNUSED, USED, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };

// Structure to hold process information
struct procinfo {
  int pid;                // Process ID
  enum procstate state;   // Process state
  uint64 sz;              // Size of process memory (bytes)
  char name[16];          // Process name
};

#endif

2. Add the System Call Number

3. Implement the System Call in kernel/sysproc.c

4. Add the System Call to the Dispatch Table in kernel/syscall.c

5. Implement the getprocs() Function in kernel/proc.c

6. Add the Function Declaration to kernel/defs.h

7. Add the System Call to user/user.h

8. Add the System Call to user/usys.pl

9. Create the User Program user/ps.c

This user program should include kernel/getproc.h and allocate a procinfo array of 64 elements.

A pointer to this array will be sent to the getprocs() system call. On return the procinfo array should be populated.

10. Update the Makefile