What is a kernel?

Thomas M. Farrelly s720@ii.uib.no
Wed, 18 Aug 1999 00:02:47 +0200

Francois-Rene Rideau wrote:
> > Is Farč really pro monolithic kernel design? Possibly. He is definitely
> > carrying pro arguments.
> I am against microkernel, that's different.
> My position, that I've developed in the past,
> is against any kernel whatsoever.
> Search the mailing-list archive for "no-kernel" or "no kernel".
> > I understand the reason a monolithic kernel would be easier to make
> > efficient [...].
> > One important point in TUNES is fine grain modularity. I don't see how a
> > monolithic kernel could be fine grained.
> Again, that's a matter of looking at things from the right point of view.
> We want modularity _at the high-level_,
> and efficient folding _at the low-level_.
> This means modular high-level objects in a suitable high-level language
> compiled into efficient low-level code at the binary level,
> without harmful runtime barrier to cross.
> At the high-level, it's modular.
> At the low-level, it looks like the whole TUNES universe
> runs into a all-encompassing monolithic "kernel".

Yes, and for that you need some way to determine dependencies among the
high-level modules in order to create efficient lowlevel code. I recall
the term 'absorbation' used in this context. I could be wrong, but
imagine that the process taking some highlevel representation and
mapping it to a lowlevel representation is called an absorbation. Then
there are some interesting things to know about the absorbation
mechanism before you even start designing it.

Lets call it A(O) - absorbing an object O.

It must be context dependent, so lets rather call it A(C,O). The reson
it neccasarily at first glance must be context dependent is: If the
system is reflective, it could in some context alter A , and then you'll
have two different A's depending on context.

But there are other reasons why it should be context dependent. First
lets look at the C, the context. C should consist of _both_ the
highlevel definition of the context _and_ the corresponding lowlevel
definition. In fact, the highlevel definition corresponds to the
structure of the context or the way it should be interpreted, while the
lowlevel definition corresponds to the state of the context.

Now A can inspect O. Where O references its context, A would look in C
using the structure ( for typechecking or just figuring out where things
are ) and build A(C,O) so that it directly references the corresponding
state. This is no problem because A has all the information it needs.

Now, the interesting things. First of all A(C,O) is a function.

But is the inverse of A(C,O) a function? The inverse of A(C,O) would be
something corresponding to decompilation or reverse compilation. But not
decompilation of an entire program, but rather one step in the
decompilation of something.

Now, that means that if you did the inverse of A(C,O) on all objects in
the system you would have built C. But C is the context and you allready
know that by defintion - its something you keep track of during runtime.

Ok - the inverse of A(C,O) is pointless to implement because you'll
never need it. This means that it's always possible to reason about
something in a highlevel way, because the decompilation is trivial. And
resoning at the highlevel can seemlessly be translated to the lowlevel
for efficiency. So that is one pro.

Another pro is: The implementation of A requires C to be kept track of
at runtime, and this appears to be a major drawback, because it can
potentially be a costy keeping track of. The good news is that only
A(C,O) will contribute any changes to C because it _is_the_ absorbation
mechanism, i.e. that which takes some subject and absorbs it into
context, thus altering the context.

Well, basically you get the snappy modulized feel on the outside
(highlevel) while it's all a big chunk on the inside. It's duck
philosophy - nice and calm over water but below the surface it paddles
like hell.

For consitency's sake I'll include a problem about A(C,O) as well.
Imagine that you do A1(C,A2). That is you make the system absorbe a new
definition of its absorbation mechanism. It doesn't cause an endless
recursive call to A, but all hell breaks loose anyway. Because
everything in context is dependent on A, so the whole context would need
to be recompiled. But this is really a standard problem that is
unavoidable at some point anyway - if you want reflection that is. You
could allways tell the user that "Disk in drive A: is full, or atempt to
absorbe A, or GURU 3f2f3:f323f - have a nice day."

> > or even, dependent on our definition of kernel, a micro kernel with
> > some framework added.
> Well, in as much as the CPU architecture forces upon us things like
> privilege levels as soon as we want to use paging,
> you might look at it this way.
> But there could be many services that don't care the least about current
> CPU privilege and don't force a barrier switch.

So just assume that these CPU privilege stuff never existed during
design of the system.

> > But technically you could have the efficiency of a huge static chunk of
> > program with the modularity of a micro kernel design.
> Repeat after me:
> the micro kernel doesn't help with high-level modularity in any way.
> microkernel is about uselessly multiplying low-level barrier crossings.

the micro kernel doesn't help with high-level modularity in any way.
microkernel is about uselessly multiplying low-level barrier crossings.

[ actually, I used cut and paste ]

> > What if you had a monolithic kernel and wanted to make it into a micro
> > kernel.
> Then I'd recommend a psycho-analysis.
> Once again:
> micro kernel isn't about high-level modularity, but low-level barriers.
> High-level modularity is gained by using a high-level modular language,
> such as CommonLISP (Genera), SML (Fox), Modula-3 (SPIN),
> Oberon (Native Oberon), Erlang (Erlang/OTP), etc.

Yeah sure, but the kernel is there in the system in some way or the
other. The question is what is neccary _inside_ the kernel ? And how
will highlevel modularity make the kernel non existent. I'm beginning to
feel like 'kernel' is just silly - very silly indeed.

( notice how I totally agree with you that no-kernel is the way to go,
It's just that I do not know what to remove or add in order to get
there. I mean it when you talk about big and small and even non existen
kernels, it sounds more like an assult to information theorists. )

I try again:

Which of the following does not fit in a microkernel:
        I/O             processes
        bootcode        ADT's
        GUI             the stack
        the heap        security
        memory management ( GC )
        networking      minesweeper

    Thomas M.  Farrelly     s720@ii.uib.no     www.lstud.ii.uib.no/~s720