Page 1 of 1

Crocos: tiny kernel for educational purposes

Posted: Tue May 05, 2009 3:23 pm
by Gduranceau
Hi all,

This is my first post here to announce that a (very) small kernel I've been working on (for now 3 years...), called CROCOS, has been made available for everybody.
Here is the project webpage.

Quick description:

CROCOS is a small opensource (GPLv3) UNIX-like kernel for x86/x86_64 systems, designed with simplicity in mind, for educational purposes. It is developed in several steps to allow people to understand how a tiny operating system can be built from scratch.
CROCOS is written in C and assembly language when needed. GNU gcc and make are used for compilation, as well as some others traditional UNIX tools.

The two main features of CROCOS are the following:

- CROCOS development is cut into distinct phases. A main phase can include sub-phases. The code for every (sub)phases is provided, so that it is possible to compare two successive phases. This way, one can extract the subset of code implementing a given feature.

- I don't find convenient the approach consisting in starting kernel development by the boot sequence, and then building kernel components on a "naked" machine or emulator. I think that implementing sensitive kernel components require robust and reliable debugging facilities. In early development phases, CROCOS provides a multiprocesses environment embedded inside one Linux process. This is achieved by using the standard setjmp and longjmp functions to perform task switching. This way, it is possible to implement a maximum of features with the comfort of Linux for debugging and tests. Boot sequence and architecture dependent developments will come later, once heavily tested tasks manager and file system will be implemented.

As of today, the development phases implemented are:
- phase 1: the kernel libc
- phase 2: the tasks manager
---- phase 2.1: a simple tasks manager
---- phase 2.2: process hierarchy and init task
---- phase 2.3: signals
---- phase 2.4: user and kernel stacks
---- phase 2.5: process synchronization (mutex)

More documentation (and the source code of course) can be found on the project webpage.

Feel free to try/comment/criticize...

Cheers - Guillaume

Re: Crocos: tiny kernel for educational purposes

Posted: Fri Oct 16, 2009 11:24 am
by Gduranceau
Hi all,

After 6 months of (irregular) work, a new development phase (phase 3: read only file system) has been added to Crocos (see description above).

This phase implements read operations for an ext2 file system (on a disk image file) and for a /proc file system, both of them being accessed through a virtual file system.
Of course, Crocos being designed for educational purposes, only the main ext2 (revision 0) features are supported. There is no support for symbolic links, behaviour control flags like compression or superblock data update, for example.

Like for phase 2 (tasks manager), phase 3 is divided into several sub-phases to help people to understand the full process of a file system implementation.

- phase 3: read only file system
---- phase 3.1: reading the file system structure
---- phase 3.2: file descriptors
---- phase 3.3: reading regular files
---- phase 3.4: reading directories
---- phase 3.5: /proc file system

In more details:
- phase 3.1 sets up the VFS and provides a way to lookup files into the ext2 file system (the stat system call allows to play with that).
- phase 3.2 provides the open/close system calls and focuses on the file descriptor concept.
- phase 3.3 provides the read system call, allowing to read files content on the ext2 file system.
- phase 3.4 provides the readdir system call, allowing to retrieve entries inside a directory.
- phase 3.5 implements the /proc file system, which allows a user process to retrieve information (pid, ppid, command line, current state) about the processes being run by the kernel.

Documentation and source code are available on Sourceforge.

Have fun - Guillaume

Re: Crocos: tiny kernel for educational purposes

Posted: Sun Oct 18, 2009 1:45 am
by redoktober
hey!
Gduranceau wrote: I don't find convenient the approach consisting in starting kernel development by the boot sequence, and then building kernel components on a "naked" machine or emulator. I think that implementing sensitive kernel components require robust and reliable debugging facilities.
i agree. it can be worse than DLL hell sometimes, and it seems you're going the right way about this.

but...
Gduranceau wrote: In early development phases, CROCOS provides a multiprocesses environment embedded inside one Linux process. This is achieved by using the standard setjmp and longjmp functions to perform task switching. This way, it is possible to implement a maximum of features with the comfort of Linux for debugging and tests. Boot sequence and architecture dependent developments will come later, once heavily tested tasks manager and file system will be implemented.
then, as i take it, your kernel runs as a process *inside* linux.
doesn't that act as an impediment, when it comes to testing if your code runs the way it should on bare metal?
i mean, i agree you'll test it later.
but, if something weird crops up, won't it be harder to fix?

maybe i'm wrong.
i hope so!
because if what you're saying truly works, then i'd like to do something similar with my kernel project..if you don't mind!

Re: Crocos: tiny kernel for educational purposes

Posted: Sun Oct 18, 2009 6:16 am
by Gduranceau
Hi,
then, as i take it, your kernel runs as a process *inside* linux.
Exactly, Crocos is actually, in early development phases, a Linux process. The only difference with a traditional process is that Crocos modifies stack pointers and the instruction pointer (through longjmp) to manage its own processes. This is sometimes confusing for gcc, which doesn't expect a program to modify stack location, and thus, performs unexpected optimizations. To workaround this, some optimization flags needs to be deactivated and setting stack pointers needs to be done carefully. The good point is that, in case of problem, gdb can be used for debugging, like for every Linux process.
doesn't that act as an impediment, when it comes to testing if your code runs the way it should on bare metal?
This is not at all an issue. When Linux is running the Crocos process, the code is running directly on the CPU. Linux is involved only to interrupt Crocos when others processes need the CPU and reschedule Crocos. No glibc function is called by Crocos. A dedicated minimal libc has been rewritten especially for that (see phase 1). Crocos code is (almost) independent from any library on the host machine. The only exceptions are:
- startup: Crocos main() function is called by Linux (not directly, see crt*.o stuff).
- Linux system calls (mainly "write" system call to write on the standard output).

Thus, when it will come to run Crocos on a bare machine, the following actions will need to be done:
- create a crt0.o object, with an entry point called by the bootloader (Grub), which will itself called the main() function.
- implement the function to display characters on the terminal (by writing into the screen memory).
i mean, i agree you'll test it later.
but, if something weird crops up, won't it be harder to fix?
Actually, I already tested it and I know that it works. Writing a small kernel was one of my computer engineer school projects, four years ago. Crocos is an evolution (and a "unix"-ification) of this project: it follows the same development pattern.
because if what you're saying truly works, then i'd like to do something similar with my kernel project..if you don't mind!
Of course, I don't mind :). And feel free to use Crocos material !

People often reduce kernel development to drivers implementation. I agree that developing a video or hard disk driver is something funny and exciting. But one shouldn't forget that a kernel manages 4 different things: processes, files, memory and devices. Files management code and a big part of processes management code can be developed and heavily tested in a Linux (or your favorite operating system) environment, which is far more easy than on a bare system.

Cheers - Guillaume

Re: Crocos: tiny kernel for educational purposes

Posted: Sun Oct 18, 2009 6:46 am
by redoktober
Gduranceau wrote: To workaround this, some optimization flags needs to be deactivated and setting stack pointers needs to be done carefully.
ah.
super!
Gduranceau wrote: When Linux is running the Crocos process, the code is running directly on the CPU. Linux is involved only to interrupt Crocos when others processes need the CPU and reschedule Crocos. No glibc function is called by Crocos. A dedicated minimal libc has been rewritten especially for that (see phase 1). Crocos code is (almost) independent from any library on the host machine. The only exceptions are:
- startup: Crocos main() function is called by Linux (not directly, see crt*.o stuff).
- Linux system calls (mainly "write" system call to write on the standard output).

Thus, when it will come to run Crocos on a bare machine, the following actions will need to be done:
- create a crt0.o object, with an entry point called by the bootloader (Grub), which will itself called the main() function.
- implement the function to display characters on the terminal (by writing into the screen memory).
okay.
that is not too big a roadblock; when the time comes to create a crt.o object, and a custom character display function, it shouldn't be too hard. again, super!
Gduranceau wrote: Of course, I don't mind :). And feel free to use Crocos material !
.
.
.
Files management code and a big part of processes management code can be developed and heavily tested in a Linux (or your favorite operating system) environment, which is far more easy than on a bare system.
i agree. but the catch is, my partner and i are writing a managed kernel, in c#.
so the catch is to first have a running .net runtime, running on bare metal, without a host OS.
luckily, i've found a way.
and unfortunately, there's no way to debug it under linux.
:(
but yeah, once the kernel is done, it could easily be ported onto a mono implementation in any linux flavor, and it'd work flawlessly.

thanks!
and good luck! you've done a lot of good stuff here.
:)

Re: Crocos: tiny kernel for educational purposes

Posted: Sun Oct 18, 2009 6:52 am
by redoktober
you know, maybe you could add a page to the wiki about this.
like, explain more about this "hosted process" thing.
or whatever you'd like to call it.
it would really help other osdevers, as well as refine the technique to a greater extent.
not that it needs it.
;)

Re: Crocos: tiny kernel for educational purposes

Posted: Sun Oct 18, 2009 7:14 am
by Gduranceau
Unfortunately, I don't know anything about c# and .net development, so I can't help on that topic :(.
you know, maybe you could add a page to the wiki about this.
like, explain more about this "hosted process" thing.
Why not... I'll took some time to do it.

Re: Crocos: tiny kernel for educational purposes

Posted: Sun Oct 18, 2009 7:21 am
by redoktober
:D
pas de probleme, mon ami!
priyanka and i will find a way.
but yeah, thanks!

well, if it's not a problem, all of us would be glad to have such an addition to the wiki.
like i said, it's very ingenious and helpful!

Re: Crocos: tiny kernel for educational purposes

Posted: Sun Oct 18, 2009 10:24 pm
by prajwal
I appreciate that this is a very ingenious idea.

But how is this better or more easy than using an emulator like Qemu/Bochs ?

If this is mainly for x86 and assuming you are using Intel paging infrastructure to do memory management - will it be plausible to come up with an implementation which runs within host os (Linux) env and can be ported to bare metal when required w/o or with minimal changes ?

Thanks & Best Regards,

Re: Crocos: tiny kernel for educational purposes

Posted: Wed Oct 28, 2009 5:45 pm
by Gduranceau
Hi,

Sorry for the late reply; I've been running out of Internet access for the last ten days (I can imagine the reaction of all the geeks out there reading this: "Wow, 10 days without Internet ! poor guy..." :D).
But how is this better or more easy than using an emulator like Qemu/Bochs ?
Even using an emulator is not very convenient (compared to running on bare metal) when it comes to implement tasks manager and file system. Indeed, at that point of development, you need to rely on your screen driver to display characters. What if there are bugs in this driver ? How to display more than the standard 80x24 characters on the screen ? How to implement efficient regression tests for those very sensitive kernel components when you can only display 24 lines at a time and when you can't do automatic comparison of what is displayed on the screen with a reference result ?

I personally do prefer using Linux as a powerful and reliable environment to develop, test and debug software than a handmade kernel embryo.
If this is mainly for x86 and assuming you are using Intel paging infrastructure to do memory management - will it be plausible to come up with an implementation which runs within host os (Linux) env and can be ported to bare metal when required w/o or with minimal changes ?
For info, Crocos can be compiled for x86 or x86_64 targets, the architecture dependent part of the source code is completely separated, and porting Crocos to others platform should not be a problem.

Anyway, memory management is something that can't be done while the kernel is embedded inside a Linux process. Indeed, as you pointed out, this needs to be achieved by configuring hardware related stuff, which can't be done in user mode (at least on Linux). Memory management will be implemented when Crocos will become independent of its host OS.

As I explained in a previous post, once the tasks manager and file system are implemented, porting the kernel to bare metal requires the two following things:
- create a crt0.o object, with an entry point called by the bootloader (Grub), which will itself called the main() function.
- implement the function to display characters on the terminal (by writing into the screen memory).
It's up to everyone to decide if they consider this as "minimal changes" :). I personally do !

Cheers - Guillaume

Re: Crocos: tiny kernel for educational purposes

Posted: Thu Oct 29, 2009 4:05 am
by prajwal
Interesting...
Even using an emulator is not very convenient (compared to running on bare metal) when it comes to implement tasks manager and file system. Indeed, at that point of development, you need to rely on your screen driver to display characters. What if there are bugs in this driver ? How to display more than the standard 80x24 characters on the screen ? How to implement efficient regression tests for those very sensitive kernel components when you can only display 24 lines at a time and when you can't do automatic comparison of what is displayed on the screen with a reference result ?
Automation is definitely possible. After all, using an emulator (qemu/bochs) will be writing data (w.r.t filesystem) to an image file
All you need to do is just write a simple file system reader on the host os which can understand your filesystem and read data from image file (floppy or hard disk). In fact when testing ATA, that is much much safer as you are sure you are not messing with real hard disk. What if there is a bug in your file system and it writes junk values into MBR of the hard disk (ofcourse assuming you are running this as a root). But, this is not what I wanted to convey. My basic point is that we can definitely automate by writing a file system reader on the host os. (That is what I do) and bet that will not be difficult as you already have your filesystem implemented in your os and you just need to port to host os :)

Regarding Task management, not sure if you are using intel infrastructure for task management. If yes, then I am surprised again as there is hardware register level manipulations involded and it is very much tightly coupled with memory management !!

Re: Crocos: tiny kernel for educational purposes

Posted: Thu Oct 29, 2009 3:31 pm
by Gduranceau
Hello,
Automation is definitely possible. After all, using an emulator (qemu/bochs) will be writing data (w.r.t filesystem) to an image file
Before being able to write any data on a file system, there's a lot to do. First, you'll probably need to be able to read data from this file system. It's a dead end (in my opinion) to try to implement write function before being sure that the read process is as bug-free as possible. Then, for Crocos, the tasks manager is implemented before the file system, and you could also want to write a kernel without file system support (there's a lot of them in the embedded world). Isn't it easier to just call the Linux system call "write" to display debug information, redirect this in a file, and compare it with the expected result ? This process is so easy that for Crocos, you just run "make check", and the whole regression test suite is run, displaying "ok" for each test which succeeds and "error" (with an error code) in case of failure.

One of the main thing I would like to show with Crocos is that OS development (like for every kind of serious software) needs heavy and automatic testing. You can't just run your code, do a few checks manually, and jump to the next cool feature you'd like to implement in your kernel. That's the best way to end-up with completely buggy code, break things you implement through the development, and give up a project you'll never be able to stabilize. All that can be done to ease testing is welcome !
In fact when testing ATA, that is much much safer as you are sure you are not messing with real hard disk. What if there is a bug in your file system and it writes junk values into MBR of the hard disk
Of course, using an emulator is mandatory to implement a disk driver. When I'm saying "running the kernel on a bare machine", I'm actually thinking "running the kernel on an emulator". I'm just clearly distinguishing between running the kernel embedded in a Linux process and running the kernel alone. For Crocos, when it will come to implement hardware dependent stuff, an emulator will be used, of course.
Regarding Task management, not sure if you are using intel infrastructure for task management. If yes, then I am surprised again as there is hardware register level manipulations involded and it is very much tightly coupled with memory management !!
It's actually possible to implement tasks switching in user mode without relying on special cpu registers. This is done thanks to setjmp/longjmp functions (which can be easily implemented for any kind of architecture) and by allocating one stack (in the heap of the kernel code #-o) per task in the kernel. Check out phase 2.1 of Crocos for a minimal tasks manager implemented with this method.

Cheers !

Re: Crocos: tiny kernel for educational purposes

Posted: Thu Oct 29, 2009 5:22 pm
by pcmattman
This is done thanks to setjmp/longjmp functions
Would that be co-operative multitasking? Or would you have a way of pre-empting tasks somehow?

Re: Crocos: tiny kernel for educational purposes

Posted: Sat Oct 31, 2009 8:17 am
by Gduranceau
Would that be co-operative multitasking? Or would you have a way of pre-empting tasks somehow?
As long as there is no handler for clock interruption (which is the case while Crocos is embedded inside a Linux process), this is indeed co-operative multitasking. At some point of development, when the kernel will be running on a bare machine (or inside an emulator), a clock interruption handler will call the scheduler at each clock tick, allowing tasks to be pre-empted.