Part 1 – System Call: ps (20 Points)
In the second part of this assignment we will be implementing pid namespaces. In order to make pid namespacing meaningful, we must give xv6 the ability to list the processes within a namespace.
This is where the ¡°ps¡± command comes in. Try running ps on your unix environment to see what it prints.
Your task is to:
1. Implement a ps syscall that will print out the pid and process name of each active process.
a. This can be done by iterating through the process table and printing the proc.pid and proc.name fields.
b. Inactive processes will have states UNUSED or EMBRYO.
c. To make things simple, you can use the cprintf function in your ps syscall to print
the process information from the kernel.
d. Do not worry about making the syscall to pass any data back to the userspace.
2. Lastly add a user program called ps that will call your shiny new ps syscall.
Your ps user program should print something like the following:
Part 2 – Pid Namespace (80 Points)
In this part of the assignment we will be adding pid namespacing to xv6. Before attempting to complete this, make sure you have a strong conceptual understanding of what namespacing means in an operating system.
One of the expected behaviours of pid namespaces is that once a pid namespace is set on a process, all child processes will inherit that pid namespacing. Make sure that you change the places where new processes are created to reflect this behavior.
We will still be storing all the processes, regardless of namespace, in the ptable. Another expected behavior of pid namespaces is that the first process in a namespace will have a namespaced pid 0. In order to do this, we will need to maintain a mapping of processes’ actual pid in the ptable, and the pid it will appear as in the namespace.
1. Add a namespace field, type int, to the proc struct
2. Add a syscall called called ¡°set_pid_ns¡± that will take an integer and set the namespace
field
3. Create a mapping of absolute pids to the namespaced pids. Make sure that the places
where processes are created and destroyed are keeping these values up to date.
a. It is acceptable to have a limited number of namespaces that are possible. In the
official solution we limited it to 4 namespaces. Like the NPROC field (the max
number of processes) we made it a c macro that can be set at build time. 4. Revisit your ps syscall. Change it so that it only prints the processes that are in the
namespace of the process that called it.
a. Make sure that you are printing the mapped namespace pid
As with any good OS assignment, you should have a sanity program. You should use this one:
We would expect that the output of the sanity program to look something like this:
Notice that the pid for the forked process shows as 0. That is the result of handing the pid namespace mapping correctly. If you did not handle the mapping correctly, we would expect that the pid for sanity in namespace 1 to be something else instead of 0.
Hints:
¡ñ You may need to set the first processes namespace to be 0 in the userinit function in proc.c.
¡ñ You can use the pinit function in proc.c to do any initialization of the pid namespace mapping that you may need to do.
¡ñ Almost all the changes you need to make for this section will be in proc.c.
¡ñ Make sure to respect the ptable lock when reading or writing from the ptable. The official
solution puts the pid namespace mapping as a field on the ptable. We then acquire and release the ptable.lock whenever reading or writing from the mapping. (Remember real operating systems are multi-threaded!)