Here comes the real cool thing: process. You will see three simple processes doing their own jobs simultaneously. A simple process scheduling policy is also introduced.
We'll create our first process. There're several stuff we should consider.
Apparently a process should have something to execute.
It's good to keep our first process as small as possible, so we'll prepare a very simple function.
The process will run it. See a/kernel/main.c
.
Processes must be managed.
The creation, scheduling, destroying must be done in the OS kernel.
We must have some metadata for each process.
This metadata is called PCB (Process Control Block).
In Orange'S the PCB is implemented as a structure struct s_proc
, see a/include/proc.h
.
You can see in the code what we store for a process in the PCB.
The x86 protect mode provides 4 levels: ring0, ring1, ring2 and ring3. The kernel will run in ring0. System processes (aka. TASKS) and user processes (aka. PROCS) will run in ring1 and ring3, respectively.
When the kernel gets control from the boot loader, it's in ring0, so if we want to run a process in ring1 or ring3, we must change the privilege level. Therefore we have pretty much things to prepare, such as GDT, LDT, TSS, etc. We have learned how to manipulate these stuf in Step 03. If you still have any questions, you may want to read Intel's IA-32 Architectures Software Developer's Manual, which can be downloaded from Intel's website.
When we have prepared the PCB and all the stuff around it, we can start the process. It would look like this:
In this snapshot, the process keeps printing chars followed by increasing numbers.
Once we have one process, we want more.
You'll see how we get more in the code. It's not hard, but we must be very careful when handling the details, such as switching between the kernel stack and the process stack (see b/
),
kernel re-enter (see c/
), saving and storing PCBs of processes (see d/
), switching PCBs in the clock interrupt handler (see e/
), etc.
At the end of e/
, we already have two processes:
It's easy to add the third, we just
- prepare the code the process will execute, and
- add an item in the PCB table
and it's done (See f/
).
We've got a kernel and several processes.
Can these processes communicate with the kernel?
Yes, via system calls.
Processes to kernel is like clients to server.
A process sends some request and the kernel responds.
Now let's implement a system call (see l/
and m/
) and make use of it (see n/
).
Currently all the processes are equal.
All of them have the same chances to run.
But sometimes we want some of them run more and some less.
You'll see how we achieve this in p/
.
The scheduling algorithm is slightly improved in r/
.
Here are three processes A, B, C with priorities 15, 5, 3 (bigger number implies higher priority) running simultaneously: