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
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
- Add a new system call
getprocs()
that will copy elements of all the proc structs in the proc array to the user level - The elements to be copied include: pid, name, status, sz
- Implement the
getprocs()
system call in kernel/proc.c - Create a shared struct definition in kernel/getproc.h
- 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