Rubix: My Simple Kernel written in C for arm
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.
Features #
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 fclose
or pclose
)
and 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 - seeset_nonblocking
.close
- closes a file descriptor.dup2
- duplicates fd fromold
tonew
.new
is closed if it already exists.pipe
- creates a pipe. fd[0] is read, fd[1] is write.fopen
- open file. Not quite POSIX, as it’s non-blockingfork
- 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.signal
is 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. Usesfork
,pipe
,exec
, anddup2
.wait
/waitpid
- both use thewait
syscall.
Processes #
- 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.
Files #
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.
Types:
- 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.
Comments