There is actually not much design, as for first attempt I aimed to make a working OS without special consideration on features nor optimizations.
The OS boots from my own boot loader, which load the kernel and initrd into a suitable address, and put boot parameters into a pre-defined memory location. The kernel then use that boot parameters to initialize things like PMM.
On memory layout, I put the kernel, kernel heap and global resources (like initrd) locates at higher-half, so that new processes duplicate the upper bytes of the page directory, last bytes point to process's CR3, and has all lower address for process's local resources.
The VFS is implemented with simplest method, a list of mount point and device:
Code: Select all
typedef struct {
char * path;
size_t path_len; // strlen(path)
dev_t dev; // the "drive handler"
} MOUNTPOINT;
For example, a call to VFS_open("/initrd/test") found a mount point at "/initrd/", and pass "test" into the drive's open() function.
I also separate the FS parser and underlying IO. Currently I have a ramdisk storage device, and
tablefs, which is a read-only filesystem that store files and meta data in a table at end of disk.
I also write a tool to pack files into an initrd with that filesystem.
Drivers are built as DSO, it's loaded and linked with kernel at load-time.
it interact with kernel by directly calling exported kernel functions, or with syscalls.
For process management, I used round-robin scheduling driven by PIT, unless yield() is called the process shall not be preempted, which is not good but it works.
Upon process creation, a mini stack and process context is created with stub function, and the stub function loads the binary, perform runtime linking/relocation, expands the heap, with it's own time-slice and pagedir, and perform clean-up when the program
ret.
A sleep queue is implemented so that a process can be removed from scheduling, waiting for signal or sleep - this way I can have many sleeping process without impacting the performance.
User-land application links with newlib and interact with the kernel via INT80 syscall.