During the second year of university, I created a kernel for the ARMv7 instruction set. I went above and beyond what was required on this project, achieving a clean design and features such as a blocked process queue, piping, kill, and a simple filesystem. This was my favourite coursework so far. I found it very interesting to learn about and implement the things that we take for granted as programmers.
I tried to stick to POSIX as much as possible, and stuck to the Linux method of having everything as either a file or process. Because pipes and standard in/out were both “files”, I was able to implement both popen and piping of the output of a process to another process.
System Calls and Helper Functions
All system calls conform to the equivalent POSIX standard, except for
close which will close the appropriate resource (no need for
set_nonblocking which is custom.
yield- ends the current time slice.
write- writes to an open file descriptor.
read- reads from an file descriptor. Returns length of read, 0 on EOF. May blocking - see
close- closes a file descriptor.
dup2- duplicates fd from
newis closed if it already exists.
pipe- creates a pipe. fd is read, fd is write.
fopen- open file. Not quite POSIX, as it’s non-blocking
fork- clones process. Return value is 0 if child, PID of child if parent, -1 if error.
exec- replaces the process with another program. PID is kept. Stack and FDs (except in/out/err) are destroyed.
exit- exits with exit code.
wait- waits for a child program to exit, and gives exit code.
kill- sends a kill signal to a process. Killed processes will not return an exit code.
signalis not yet implemented.
setpriority- set priority of child process.
set_nonblocking- is not POSIX, unfortunately. Set pipe non-blocking.
The following functions use system calls to provide a higher function:
popen- opens a process and returns a FD. Uses
waitpid- both use the
- time slicing - timer based timer slices.
- priority-based - priority(P) = priority_base(P) + slices_since_last_ran(P)
- blocked queue - for processes waiting for a process or file resource.
- process ownership - processes have a parent, which can kill/wait them.
- process groups - a limited type of process group, where all processes that share a parent and the parent itself are in a group.
The kernel allows the use of file descriptors to refer to resources. They are implemented under the hood using function pointers, which means that the main part of the kernel doesn’t even know what type of file they are. Can be blocking or not.
- pipe - Pointed to by a FD.
- in/out/err - these are “files” too!
- filesystem - Files are limited to 256 bytes with a maximum of 10 files.