A process is a running program.
Running many processes at a time is done by virtualizing the CPU (like time-sharing).

Process

To understand what constitutes a process, we have to understand its machine state: what a program can read or update when it is running.

Machine State: Key Components

Memory (Address Space): The code (instructions) and the data the program uses are stored in memory. The “address space” of a process is all the memory addresses it can use.
Registers: Registers are very small storage locations inside the CPU.

Process API

Some APIs for a process:
Create: Create new process
Destroy: Destroy process
Wait: Stop process
Miscellaneous Control: Eg. Suspend
Status: Check process status

Process Creation

Program initially resides on disk in some kind of executable format.
OS must load its code and any static data into memory, into the address space of the process.
Modern OS perform loading lazily (loading pieces of code or data only as they are needed instead of all at once).
Once code and static data is loaded into memory, some memory must be allocated in stack and heap. The OS will also do other initialization tasks, particularly related to input/output (I/O). For example, in UNIX systems, each process by default has three open file descriptors.

Now the process can start the program running at the entry point, namely main()

Process States

3 states for a process:
Running: A process is running on a processor.
Ready: A process is ready to run.
Blocked: Not ready to run.

Figure 4.2 Process - State Transitions.png

Data Structures

To track the state of each process, the OS likely will keep some kind of process list for all processes that are ready and some additional information to track which process is currently running.

What type of information an OS needs to track about each process in the xv6 kernel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// the registers xv6 will save and restore
// to stop and subsequently restart a process
struct context {
int eip;
int esp;
int ebx;
int ecx;
int edx;
int esi;
int edi;
int ebp;
};

// the different states a process can be in
enum proc_state { UNUSED, EMBRYO, SLEEPING,
RUNNABLE, RUNNING, ZOMBIE };

// the information xv6 tracks about each process
// including its register context and state
struct proc {
char *mem; // Start of process memory
uint sz; // Size of process memory
char *kstack; // Bottom of kernel stack for this process
enum proc_state state; // Process state
int pid; // Process ID
struct proc *parent; // Parent process
void *chan; // If !zero, sleeping on chan
int killed; // If !zero, has been killed
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
struct context context; // Switch here to run process
struct trapframe *tf; // Trap frame for the current interrupt
};