A process that is suspended is actually in the ready state.
Blocked
Terminated
While it may be necessary to consider this state temporarily, terminated processes are simply removed from the system and their resources are reclaimed.
Read section 4.5 about the data structures used to represent a process. Also take a look at our xv6-riscv code, specifically kernel/proc.h. How do those definitions compare to what you see in the book? How do the process states map to the ones discussed in the book?
Looking at the proc_state options in the code, which of those options describes the state of a process after it has been terminated but before it has been fully eliminated from the system?
Looking at the proc_state options in the code, which of those options describes the state of the process when it is in what the book described as the "ready" state?
In kernel/proc.c you will find a function that is used to allocate a new "process id" (usually referred to as a pid) for a to-be-created process. Locate this function (you should recognize the acronym name of it when you see it). How does the system determine this pid?
Now we look at the Process API chapter which discusses important system calls that the kernel provides to enable us to manage processes. Start by reading section 5.1 about the fork system call, quite possibly the weirdest function you have seen. Compile and run the code in figure 5.1, which can also be found in the ostep/cpu-api/p1.c code file. (You can build all programs by doing make all from that directory, then delete them when you are done by running make clean.)
Make sure you really understand which lines from that file are executed in the child process, which lines are executed in the parent, and which are executed in both.
This is a bit more open-ended: Change program 1 so that it creates a specific number of children (stored in some variable N). You need to be careful, as a naive approach by wrapping everything in a for loop will create many more children (e.g. 7 children if you ask it for 3).
Each child continues execution exactly where the fork() call occurs, and if in the middle of the loop it means that the loop will also continue in the child process, not just in the parent process. You need to make sure children exit out of the for loop.
Now read through section 5.2, which discusses the wait() call that can be used by a process to wait for one of its children to end. Compile and run the program in Figure 5.2, also found in the file under ostep/cpu-intro/p2.c.
This is a bit more open-ended: Change this program p2 so that it creates a specific number of children (stored in some variable N), then waits for them all to finish and records the pids in the order the children finished. After that, it prints out all the pids in that same order.
The original program continues executing just below the execvp line.
The original program doesnβt run any more.
Read the documentation for execvp by running man execvp. What happens if the call fails to start the new program? Try to make the example p3 fail by calling a program that doesnβt exist (for example wce instead of wc).
The original program will only continue to run if there was an error in execvp executing the new program (for example if the file for the new program could not be found).
Modify the provided program so that it instead executes the ls program just as if we had typed: ls -l ... You should see as a result a list of the different directories like cpu-api.
You will need to extend the array used to provide arguments to the new program, as the call described above needs three different entries in the command line.
Read through sections 5.4 and 5.5 to get further understanding of how these tools are used, and in particular how the system manages multiple users and what they each can do.