Microkernel Design Implementation

Discussions on more advanced topics such as monolithic vs micro-kernels, transactional memory models, and paging vs segmentation should go here. Use this forum to expand and improve the wiki!
User avatar
liquid.silver
Member
Member
Posts: 46
Joined: Sat Jun 30, 2007 12:07 pm
Location: South Africa
Contact:

Microkernel Design Implementation

Post 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.
Craze Frog
Member
Member
Posts: 368
Joined: Sun Sep 23, 2007 4:52 am

Post by Craze Frog »

You could take a look at Asgard: http://sartoris.sourceforge.net/download.html .
User avatar
liquid.silver
Member
Member
Posts: 46
Joined: Sat Jun 30, 2007 12:07 pm
Location: South Africa
Contact:

Post 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)
User avatar
liquid.silver
Member
Member
Posts: 46
Joined: Sat Jun 30, 2007 12:07 pm
Location: South Africa
Contact:

Post 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.
Craze Frog
Member
Member
Posts: 368
Joined: Sun Sep 23, 2007 4:52 am

Post 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.
User avatar
liquid.silver
Member
Member
Posts: 46
Joined: Sat Jun 30, 2007 12:07 pm
Location: South Africa
Contact:

Post 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?
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Post 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
guch
Posts: 1
Joined: Thu Dec 13, 2007 5:38 am

Post 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
Craze Frog
Member
Member
Posts: 368
Joined: Sun Sep 23, 2007 4:52 am

Post by Craze Frog »

Please continue it!
elfenix
Member
Member
Posts: 50
Joined: Sun Dec 02, 2007 1:24 pm
Libera.chat IRC: elfenix
Location: United States
Contact:

Post 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.
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post 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.
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Post 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 :).
mrvn
Member
Member
Posts: 43
Joined: Tue Mar 11, 2008 6:56 am

Post 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]
Life - Don't talk to me about LIFE!
So long and thanks for all the fish.
iammisc
Member
Member
Posts: 269
Joined: Thu Nov 09, 2006 6:23 pm

Post 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.
User avatar
piranha
Member
Member
Posts: 1391
Joined: Thu Dec 21, 2006 7:42 pm
Location: Unknown. Momentum is pretty certain, however.
Contact:

Post 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
SeaOS: Adding VT-x, networking, and ARM support
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
Post Reply