Page 1 of 2

Microkernel Design Implementation

Posted: Fri Dec 07, 2007 1:13 pm
by liquid.silver
I have looked but can't find any good info on microkernel design implementation details. If i missed something you're free to tell me that i'm an idiot.

I understand that the principle of microkernels is to move drivers to user space as servers and use ipc, but i don't understand how to put it all together. I mean how does a program get access to the right driver? I want a unix-like file design, but how do the programs access the file server and so forth? I'm not referring to using a ram disk to load the drivers but rather how they communicate with the programs. I also understand that some of this i must decide to shape my own os uniquely, but can you please just give me a rough idea. I don't mind incorporating some of the vital stuff into the kernel, but just not everything. I hope i'm being clear enough.

Posted: Fri Dec 07, 2007 3:29 pm
by Craze Frog
You could take a look at Asgard: http://sartoris.sourceforge.net/download.html .

Posted: Fri Dec 07, 2007 5:01 pm
by liquid.silver
That looks like it has potential. I can't tell as i'm not at home for a while and i have to use my phone to access the net, so i can't look at the source code. Is it your os?

I was more looking at discussing it here. If it's your os, could you please outline how it works to join the servers and kernel in a working environment.

I was also thinking: Minix is a microkernel. Does anyone know how it interfaces with its servers? (once again i can't get the source code at hand myself)

Posted: Sat Dec 08, 2007 8:00 am
by liquid.silver
I had a idea of a possible method. There will be a 'super' process that will be responsible for maintaining a list of servers. The kernel must just make sure it's accessible to all processes. Then you just ask the super process for the name of the file server to open a file. Is this similar to other microkernels? Any problems? Please comment.

Posted: Sat Dec 08, 2007 9:04 am
by Craze Frog
No, it's not my os. The 'super' process you are talking about sounds like what is usually called "the root task" or sigma0 (no clue why).

If you have use ports for the IPC, you can just make sure the root task reserves a predefined port which processes sends messages to when they want to know what other ports are available.

Posted: Sat Dec 08, 2007 11:21 am
by liquid.silver
I don't use ports. I want services to rather be referred to by a name than a number. It should allow a more programmer friendly system. My messages are per process and no ports. Destination is another process. The super process will just have a standard process id and so communication should be fairly simple. I have synchronous ipc called messages and asynchronous ipc called signals. Messages return a value, so a process would contact the super process and ask for a pipe with messages. It would get a pipe end returned and can then write the name of the server wanted to the pipe. The super process will then reply with the pid of the server and the process can then contact the respected server. The only problem i can think of would happen if a server crashes as the pid would then be invalid and communication would have to be reestablished from the begining, including getting a new pid from the super. Ports would solve some of those problems, so maybe they would be a good idea... But i don't want to have standard ports, so then they wouldn't really serve any purpose...

I guess i'll just presume servers won't randomly crash and that if they do it might get a tad ugly. Also there will be a few main servers like the file server and as long as they don't crash, it won't matter to the normal processes. If a server further down the line, like a fat32 server, crashed, the main server must be equipped to deal with it. How's that sound?

Posted: Mon Dec 10, 2007 7:36 am
by jal
liquid.silver wrote:I don't use ports. I want services to rather be referred to by a name than a number. (...) so a process would contact the super process and ask for a pipe with messages. It would get a pipe end returned and can then write the name of the server wanted to the pipe. (...) How's that sound?
Port or pipe, name or number, these are all names for some sort of abstraction. The way you talk about it, it seems like you think these are some kind of fixed, unchangeable things. I don't see why you couldn't call a named pipe a port, or why you couldn't access ports by names instead of numbers.

The basics are: you want to send certain data to a certain process, in order for that process to do something with it, and maybe return you some data in return. Such a process could be called a 'service', but it may very well be a program like all others. If a program wants to access such a service, it must know whether the service is available and where it resides. A service may have a unique 'name', and/or reside at a unique 'address'. A 'name' may very well be numeric, an 'address' very well alphanumeric - remember, they're only abstractions. If you want to do something, you must know what to do, so you know 'who' (i.e. what process) to 'call' (i.e. send some data to).

If your OS has fixed addresses for fixed services (similar to e.g. TCP/IP), you can just use that address. If your OS has fixed names instead of fixed addresses, you can use the name instead. Or, if your OS requires an address, but has no fixed addresses, you request the OS for the address of a service with a certain name.

Alternatively, you could request the OS for a certain interface, and the OS provides you with a process (its name or address) or a list of processes supporting that interface (if more than one). Then you can query that process or processes, to see whether it provides the service you want.


JAL

Posted: Thu Dec 13, 2007 5:41 am
by guch
I started writing a tutorial on Sartoris (the microkernel underlying Asgard) a while back. It's not finished yet, but you can check it out here:

http://sartoris-microkernel.blogspot.com/2006/06/0.html

Posted: Sun Dec 16, 2007 7:24 am
by Craze Frog
Please continue it!

Posted: Tue Dec 18, 2007 8:22 pm
by elfenix
The principle problem you're going to have in any microkernel design is the time it takes to get a chunk of data from a given program to a service, and then get the return chunk back to the program.

If you have one 'super' service that handles the communication, than every chunk of data has to go through a path like this:

your task -> super service -> driver -> super service -> your task

Now, in doing this you have used 4 context switches. Also, it's likely that even simple tasks will require multiple tasks before you are done.

Now, if you want, you can ask the super service for a connection to a driver. Then your path becomes simpler:

your task -> super service -> your task
your task -> driver -> your task

Now, the minimal case uses the same number of switches as before, but now, you have a pipeline between your service and the driver - so following system calls only use 2 context switches. Very well defined system calls can have predefined connections you use, in order to skip the first step.

Now, you can also think about reducing the amount of data copying that must be done on during the trip. Let's say that we want to read a page from a file on disk. Copying the page during the switches would be a very expensive operation. But, by the same token, if you want to reposition the on screen cursor to a new x/y value, copying a couple integers for each switch is trivial to setup that would be required for not copying them.

Posted: Tue Dec 18, 2007 11:11 pm
by bewing
You have a good point, unless the "super service" queues and batches its service requests. Then there is just one context switch for many data packets at a time.

Posted: Wed Dec 19, 2007 4:23 am
by jal
Fate wrote:If you have one 'super' service that handles the communication, than every chunk of data has to go through a path like this:

your task -> super service -> driver -> super service -> your task

Now, in doing this you have used 4 context switches.
If one considers the 'super service' to be the kernel, there's no need for a context switch to that service, a simple stack switch (from user stack to kernel stack) suffices. Then the kernel can copy the message (or, on paged CPUs, simply page in the message, provided it's on page boundaries etc.), do the context switch to the service (1st context switch), have the service reply, copy/page in the reply, perform a context switch to the original sender (2nd context switch). I think that all micro kernels have the message passing at the core of their functionality, along with stuff like synchronization primitives.


JAL

P.S. I'm just recovering from a short illness and have still a hell of a cold. If the above is bullshit, keep this in mind please :).

Posted: Tue Mar 11, 2008 8:12 am
by mrvn
The principle problem you're going to have in any microkernel design is the time it takes to get a chunk of data from a given program to a service, and then get the return chunk back to the program.
A common feature in such a design is the option of granting access to pages from one process to another.

So instead of copying 64k of data you write to a file from the application to the super, to the virtual filesystem, back to the super, to the actual filesytem, back to super, to the raid layer, back to super, to the scsi layer, to the super, to the dma engine, notice how much copying you do and how many task switches you can have?

So instead of all that copying you send a message that includes read access to the 64k of memory you want to write. The super then just copies the pointer around between the services and never touches the 64k of memory.

If you have a flat address space you can even send structures including pointers as they will still be valid in the recievers address space (given you granted access).



As for the initial problem of how to know what services there are and how to contact them:

Usualy you have one super service. Every process you start would either know about that by default (fixed address or name) or recieve it as an argument. Actually passing the process a list of available services on start of day is a very nice security feature. You can limit the capabilities a process can call upon by limiting the services it gets told about. So if a process should do no file I/O then you don't give it the File I/O service when started. For this to work you have to make sure though that a process can never increase the amount of services it has.

MfG
Goswin
[/quote]

Posted: Tue Mar 11, 2008 8:47 pm
by iammisc
In my microkernel, the kernel starts only one task: the init task. The init task is responsible for starting and keeping track of all the servers. The init task has a well-defined process identifier. When an app wants to use a server, it asks the init task for the pid of the server it wants. It then can communicate directly with the server it requested. If you would like to see the source i can attach it.

Posted: Wed Mar 12, 2008 8:48 am
by piranha
My init task will scan all devices required for loading the root drive, load all modules for that. If it can't find one, it might be able to connect to the internet to download one, or insert a CD with a bunch on them and find it there.
Then it will mount root, and pass control to /bin/init.

-JL