Torvalds on the Microkernel Debate
diegocgteleline.es writes "Linus Torvalds has chimed in on the recently flamed-up (again) micro vs monolithic kernel, but this time with an interesting and unexpected point of view. From the article: 'The real issue, and it's really fundamental, is the issue of sharing address spaces. Nothing else really matters. Everything else ends up flowing from that fundamental question: do you share the address space with the caller or put in slightly different terms: can the callee look at and change the callers state as if it were its own (and the other way around)?'"
This my favorite Linus quote from that whole thread:
"In the UNIX world, we're very used to the notion of having
many small programs that do one thing, and do it well. And
then connecting those programs with pipes, and solving
often quite complicated problems with simple and independent
building blocks. And this is considered good programming.
That's the microkernel approach. It's undeniably a really
good approach, and it makes it easy to do some complex
things using a few basic building blocks. I'm not arguing
against it at all."
He basically continues his previous argument that monolithic kernels are more efficient and easier to implement. Microkernels may seem simpler, but they have complexity in implementing all but the simple tasks. Microkernels have a more marketable name. "Microkernel" just sounds more advanced than "monolithic". He finishes off with the observation that the term "hybrid kernel" is a trick to grab marketing buzz from the microkernel side of things.
My other first post is car post.
pfff, Linus, what would he know?
Philosophy.
As fast as C++ would be a fairly lame goal for a kernel.
That's SOOO 1992!
Linus FTFA:
"The fundamental result of access space separation is that you can't share data structures. That means that you can't share locking, it means that you must copy any shared data, and that in turn means that you have a much harder time handling coherency. All your algorithms basically end up being distributed algorithms.
And anybody who tells you that distributed algorithms are "simpler" is just so full of sh*t that it's not even funny.
Microkernels are much harder to write and maintain exactly because of this issue. You can do simple things easily - and in particular, you can do things where the information only passes in one direction quite easily, but anythign else is much much harder, because there is no "shared state" (by design). And in the absense of shared state, you have a hell of a lot of problems trying to make any decision that spans more than one entity in the system.
And I'm not just saying that. This is a fact. It's a fact that has been shown in practice over and over again, not just in kernels. But it's been shown in operating systems too - and not just once. The whole "microkernels are simpler" argument is just bull, and it is clearly shown to be bull by the fact that whenever you compare the speed of development of a microkernel and a traditional kernel, the traditional kernel wins. By a huge amount, too.
The whole argument that microkernels are somehow "more secure" or "more stable" is also total crap. The fact that each individual piece is simple and secure does not make the aggregate either simple or secure."
Forgive me if I am wrong, but doesn't windows have a bloated kernel? (I really know nothing about the internals of computers... but it would seem like this makes sense) Obviously it would seem that windows isn't so great when it comes to stability or security... So, lets learn from what windows did wrong, and break things down to small parts that are easier to work with, more secure, and everything everyone else voting for the micro kernel idea said.
Anyways, what do the Ubtuntu guys have to say about this? They seem to be doing pretty well...
Scott Swezey
The whole discussion of micro-kernel vs monolithic kernel is totally pointless. All popular OS kernels are monolithic. We can get back to the debate when we have a working fast microkernel in the market that is actually competitive.
Linus is a pragmatist. He didn't write Linux for academic purpose. He wanted it to work.
But you can always prove him wrong by showing him the code, and I bet he'd be glad to accept he was wrong.
10 messages posted and TFA is already /.ed
Quick slashdoteffect there, that forum is already down. Anyhow.. mirror: http://www.mirrordot.org/stories/3f6b22ec7a7cffcf2 847b92cd5dec7e7/index.html
Any chance we could do this with my long distance phone service?
A-Bomb
http://pastebin.ca/54695
http://www.oreilly.com/catalog/opensources/book/ap pa.html
"The whole "microkernels are simpler" argument is just bull, and it is clearly shown to be bull by the fact that whenever you compare the speed of development of a microkernel and a traditional kernel,the traditional kernel wins. By a huge amount, too. He goes on to say, "It's ludicrous how microkernel proponents claim that their system is "simpler" than a traditional kernel. It's not. It's much much more complicated, exactly because of the barriers that it has raised between data structures." He states that the most fundamental issue is the sharing of address spaces. "Nothing else really matters. Everything else ends up flowing from that fundamental question: do you share the address space with the caller, or put in slightly different terms: can the callee look at and change the callers state as if it were its own?"
Insinct is stronger than Upbringing - Irish Proverb
I'm pretty sure it's a shit load of work to port the linux kernel to become a micro kernel. Anyway got the spare time to do that?
PS, besides porting all parts of the kernel you first need to redesign the kernel so it can cope with the micro kernel idea (and structural limitations).
As soon as GNU Hurd is mature we'll have a drop-in replacement (right?).
"All popular OS kernels are monolithic."
I must've skipped into a parallel world where Windows XP, Windows 2000, and Windows 2003 were not somehow based on the microkernel NT Exective.
--
Internet Explorer (n): Another bug -- that is, a feature that can't be turned off -- in Windows.
Buy a copy of Windows Internals and educate yourself. Specifically, page 36: Is Windows a Microkernel-Based System?
Windows and Linux are not THAT different as far as kernel architecture is concerned.
I think Linus hit the spot by pointing out that the future of home computing is going to to focus on parallel processing - it's 2006 and all my computers, including my LAPTOP, are dual-processor systems.
By 2010 I suspect at least desktops are 4-CPU systems and as the numbers of cores increase one of the large drawbacks of microkernels raises it's ugly head: microkernels turn simple locking algorithms into distributed computing-style algorithms.
Every game developer tells us how difficult it is to write multi-threaded code for even our monolithic operating systems (Windows, Linux, OSX). In microkernels you constantly have to worry how to share data with other threads as you can't trust them to give even correct pointers! If you would explicitly trust them, then a single failure at any driver or module would bring down the whole system - just like in monolithic kernels but with a performance penalty that scales nicely with the number of cores. What's even worse is that at a multi-core environment you'll have to be very, very careful when designing and implementing the distribution algorithms or a simple user-space program could easily crash the system or gain superuser privileges.
Capitalization is the difference between "Helping your uncle jack off a horse" and "Helping your uncle Jack off a horse"
http://www.mklinux.org/
That would be monolithic+marketing.
MacOS X is no microkernel system. It does have Mach, sure. Mach is arguably not a microkernel by today's standards, and in any case MacOS X has a full BSD kernel bolted onto the Mach kernel. Mach and BSD are sharing address space. In other words, it's not a microkernel.
NT is the same way.
I don't know all that much about NetWare, but I'd never before heard anyone claim it to be a microkernel. It's not terribly popular anyway. (it was, but back then I'm sure it wasn't a microkernel system) ReactOS isn't much yet. BeOS died for unrelated reasons, so we really can't judge.
Monolithic kernels can be very modular. Microkernels can get really convoluted as the developers struggle with the stupid restrictions.
Individual pieces aren't really any simpler either. In fact, if you want your kernel to scale, to work well with lots of processes, you are going to run into a simple problem: multitasking.
Consider a filesystem driver in a monolithic kernel. If a dozen or so processes are all doing filesystem calls, then, assuming proper locking and in-kernel pre-emption, there's no problem - each process that executes the call enters kernel mode and starts executing the relevant kernel code immediately. If you have a multiprocessor machine, they could even be executing the calls simultaneously. If the processes have different priorities, those priorities will affect the CPU time they get when processing the call too, just as they should.
Now consider a microkernel. The filesystem driver is a separate server process. Executing a system call means sending a message to that server and waiting for an answer. Now, what happens if the server is already executing another call ? The calling process blocks, possibly for a long time if there's lots of other requests queued up. This is an especially fun situation if the calling process has a higher priority than some CPU-consuming process, which in turn has a higher priority than the filesystem server. But, even if there are no other queued requests, and the server is ready and waiting, there's no guarantee that it will be scheduled for execution next, so latencies will be higher on average than on a monolithic kernel even in the best case.
Sure, there are ways around this. The server could be multi-threaded, for example. But how many threads should it spawn ? And how much system resources are they going to waste ? A monolithic kernel has none of these problems.
I don't know if a microkernel is better than monolithic kernel, but it sure isn't simpler - not if you want performance or scalability from it, but if you don't, then a monolithic kernel can be made pretty simple too...
Forget magic. Any technology distinguishable from divine power is insufficiently advanced.
By today's standards, Mach is not much of a microkernel. Mach has been disowned by microkernel proponents because it was so big and nasty.
MacOS has that sharing address space with the monolithic BSD kernel. So a semi-microkernel and a monolithic kernel are firmly bolted together. That's only a microkernel if your degree is in marketing.
"You can do simple things easily - and in particular, you can do things where the information only passes in one direction quite easily, but anythign else is much much harder, because there is no "shared state" (by design). And in the absense of shared state, you have a hell of a lot of problems trying to make any decision that spans more than one entity in the system."
I think you're looking at this the wrong way around.
There has been a lot of research into this over the past 40 years, ever since Dijkstra first talked about coordination on a really big scale in the THE operating system. Any decent CS program has a class on distributed programming. Any decent SW architect can break down these different parts of the OS into weakly-connected pieces that communicate via a message passing interface (check out this comment by a guy talking about how Dragonfly BSD does this).
It's obvious that breaking something like your process dispatcher into a set of processes or threads is silly, but that can be easily separated from the core context switcher. Most device driver bottom halves live fine as a userland process (each with a message-passing interface to their top-halves).
If you're compiling for an embedded system, I'm sure you could even entirely remove the interface via some #define magic; only debug designs could actually have things in separate address spaces.
The point I'm trying to make is: yes, you can access these fancy data structures inside the same address space, but you still have to serialize the access, otherwise your kernel could get into a strange state. If you mapped out the state diagram of your kernel, you'd want the transistions to be explicit and synchronized.
Once you introduce the abstraction that does this, how much harder is it to make that work between processes as well as between threads in the kernel? How much of a benefit do you gain by not having random poorly-written chunks pissing over memory?
How about security benefits from state-machine breakdowns being controlled and sectioned off from the rest of the machine? A buffer overflow is just a clever way of breaking a state diagram and adding your own state where you have control over the IP; by being in a separate address space, that poorly written module can't interact with the rest of the system to give elevated privileges for the attacker (unless, of course, they find flaws in more of the state machines and can chain them all together, which is highly unlikely!).
Clearly there is a security benefit as much as there is a consistency benefit. Provably correct systems will always be better.
--
Internet Explorer (n): Another bug -- that is, a feature that can't be turned off -- in Windows.
Hi folks,
I worked two years for a society that was developing its own micro-kernel system, for embedded targets. I was involved in system programing and adaptation of the whole compiler tools, based on GCC chain.
Linus is right: basic problem is address space sharing, and if you want to implement memory protection, you rapidly falls into address space fragmentation problem.
The main advantage of the system I worked on wasn't really its micro-kernel architecture, but the fact that its design allowed to suppress most of glue code that is needed between a C++ program and a more classic system.
In my opinion, micro-kernel architecture has the same advantage and drawbacks that so-called "object-oriented" programing scheme : it is somewhat intellectually seducive for presentations but it is just a tool.
It would certainly be intersting for Linux to provide the dynamic link management specificities of a micro-kernel system, for instance to allow someone to quickly modify IP stack for its own purpose, but should the whole system being design that way ? I am not sure.
If you want to have an idea of the problem encountered with programing for these systems, one can look at the history of the AmigaOS, which have a design very close to a micro-kernel one.
If the Linux kernel had have been coded using Forth.
Just saying.
abstraction and state isolation considered harmful
That's a pretty big assumption. Or rather, you have basically taken all the hard parts of doing shared code and said "Let's hope someone else already solved this for us".
Sooooo, it's easy to have someone else handle the multi-process bits in a monolithic design. But when it comes to writing services for microkernels suddenly everyone is an idiot?
Besides, as Linus pointed out, when data is going one way microkernels are easy. And in the case of file systems that is really the case. Sure multiple processes can access it at once, but the time scale on handling the incoming signals is extremely fast compared to waiting for data from disk. Only a really, *really* incompetent idiot would write such a server which blocked until the read was finished.
In the end it boils down to the old question centralisation vs. local autonomy. Centralisation is fine for keeping state, it is fine for enforcing a thoroughly similar approach to everything, it helps with 'single points of contact'. Local autonomy helps with less administrational effort, with clearly defined information paths and with clear responsibilities, thus with keeping problems locally.
Both approaches have their merits, and in the real world you will never see a purely central organisation or a purely localized organisation. Every organisation is somehow swinging between both extrema, going more central at one point "to leverage synergies and increase efficiency", or is starting outsourcing and reorganizing itself into profit centers, to "overcome bureaucracy, to clearly define responsibilities and to cut down on administrational spending".
The limits are given by the speed information is created, sent and decoded within the different organisational paths. An increase in Inter Process Communication speed will help with a more modularized microkernel approach, an increase in number and complexity of concurrent requests demands a more centralized kernel.
In the end it boils down to the fact, that transactions have to be atomar operations, either being executed completely or rolled back completely if not finished. Centralized systems are inherently transactional, especially if they are executing tasks sequentially. The limit is given with the numbers of transactions that can be executed per time unit. Parallel execution demands operations to be as independent of each other as possible, thus increasing design efforts, but once the task is (nearly) interlock free, a modularized approach helps with faster, better maintenable code.
Name: Linus Torvalds (torvalds AT osdl.org) 5/9/06
___________________
_Arthur (Arthur_ AT sympatico.ca) on 5/9/06 wrote:
I found that distinction between microkernels and "monolithic" kernels useful: With microkernels, when you call a system service, a "message" is generated to be handled by the kernel *task*, to be dispatched to the proper handler (task). There is likely to be at least 2 levels of task-switching (and ring-level switching) in a microkernel call.
___________________
I don't think you should focus on implementation details.
For example, the task-switching could be basically hidden by hardware, and a "ukernel task switch" is not necessarily the same as a traditional task switch, because you may have things - hardware or software conventions - that basically might turn it into something that acts more like a normal subroutine call.
To make a stupid analogy: a function call is certainly "more expensive" than a straight jump (because the function call implies the setup for returning, and the return itself). But you can optimize certain function calls into plain jumps - and it's such a common optimization that it has a name of its own ("tailcall conversion").
In a similar manner, those task switches for the system call have very specific semantics, so it's possible to do them as less than "real" task-switches.
So I wouldn't focus on them, since they aren't necessarily even the biggest performance problem of an ukernel.
The real issue, and it's really fundamental, is the issue of sharing address spaces. Nothing else really matters. Everything else ends up flowing from that fundamental question: do you share the address space with the caller, or put in slightly different terms: can the callee look at and change the callers state as if it were its own (and the other way around)?
Even for a monolithic kernel, the answer is a very emphatic no when you cross from user space into kernel space. Obviously the user space program cannot change kernel state, but it is equally true that the kernel cannot just consider user space to be equivalent to its own data structures (it might use the exact same physical instructions, but it cannot trust the user pointers, which means that in practice, they are totally different things from kernel pointers).
That's another example of where "implementation" doesn't much matter, this time in the reverse sense. When a kernel accesses user space, the actual implementation of that - depending on hw concepts and implementation - may be exactly the same as when it accesses its own data structures: a normal "load" or "store". But despite that identical low-level implementation, there are high-level issues that radically differ.
And that separation of "access space" is a really big deal. I say "access space", because it really is something conceptually different from "address space". The two parts may even "share" the address space (in a monolithic kernel they normally do), and that has huge advantages (no TLB issues etc), but there are issues that means that you end up having protection differences or simply semantic differences between the accesses.
(Where one common example of "semantic" difference might be that one "access space" might take a page fault, while another one is guaranteed to be pinned down - this has some really huge issues for locking around the access, and for dead-lock avoidance etc etc).
So in a traditional kernel, you usually would share the address space, but you'd have protection issues and some semantic differences that mean that the kernel and user space can't access each other freely. And that makes for some really big issues, but a traditional kernel very much tries to minimize them. And most importantly, a traditional kernel shares the access space across all the basic system calls, so that user/kernel difference is the only access space boundary.
Now, the real problem with split acce
Here is some good readign amterial, maybe people should read and _understand_ it before posting on the subject..
i tem.5d61c1d591162e4b0ef1bd108bcd45f3/index.jsp?&pN ame=computer_level1_article&TheCat=1005&path=compu ter/homepage/0506&file=cover1.xml&xsl=article.xsl&
0 ,1144,0131429388,00.html
This does not mean you have to agree with the guy.
http://www.computer.org/portal/site/computer/menu
http://vig.prenhall.com/catalog/academic/product/
And what is your definition of a "Traditional Kernel?" If you wanna get really technical, start looking back at ENIAC and UNIVAC, from the '50s/60s.
Still waiting on Serviscope_minor to wake up to fucking reality and realize that Jessica Price isn't going to fuck him.
Most of the critical RT operating systems will have some kind of a ukernel architecture. velOSity is one such ukernel, it is used by the INTEGRITY OS made by Green Hills. The next time you fly on the plane it will probably be a ukernel that will make sure you land safely, not a monolithic blob that makes it impossible to mathematically prove security policies, which you would want in real important situations.
Linus will obviously defend his architecture choice. I don't see him all of the sudden deciding that ukernels are in any way "better", it is like having Microsoft opening the source code for Windows.
Back in the day the main argument was performance -- the cost of context switches. Today with machines that are probably 10x or 20x faster, context switches won't be such a big hit. So Linus had to come up with some other explanation -- "hard to code". The argument that there are no "real" OSes with microkernels today doesn't hold either.
Linus is a pragmatist. He didn't write Linux for academic purpose. He wanted it to work. I don't know but an OS that flies thousands of people over the Atlantic every day without a crash is called a "working" OS in my book. And that OS is probably a ukernel.
IANAKH (I am not a kernel hacker)
I'd love to hear some examples. It would be nice to see an example where something that's easy in a monolithic kernel is difficult in a microkernel. See, I imagine this bunch of distinct services all happily calling each other for what they need; I'd like to know more about how the need for complex distributed algorithms arises.
Xenu loves you!
and yet, BEOS showed that C++ was blazing fast for a kernel.
I prefer the "u" in honour as it seems to be missing these days.
So how does giving each program its own memory space, but having chunks of memory mapped into multiple memory spaces fit into the scheme of things? I'm confused!
"The fundamental result of access space separation is that you can't share data structures."
That's not true. You can share parts of your address space if you want to. Of course the trouble is that if you share bits of your internal state in a writeable way, anyone who can modify it can also screw it up.
"The whole 'microkernels are simpler' argument is just bull, and it is clearly shown to be bull by the fact that whenever you compare the speed of development of a microkernel and a traditional kernel, the traditional kernel wins. By a huge amount, too."
This could also be due to a general difference of philosophy and not just the kernel style issue. Worse is better.
But I also want the Loch Ness Monster to exist and assist me in my conquest of Mars.
Quite simply, just look at HURD. Didn't they finish the initial work involved in porting to the L4 kernel before starting to pursue the Coyotos kernel?
Do you see what I did there?
Distributed algorithms are of course difficult to implement with a f***ed up language like C.
Here, it seems, the means justify the ends. Linus basically says "I won't take any challenges".
Linus tells me that we can never write a proper scalable OS for a NUMA machine, or a modular system that can serve well to parallel I/O systems and the like. I highly disagree.
Because these things are not pipe dreams, they have been done. IBM guys have made amazingly abstract and modular OS stuff and they've been using them for years, so I think it's rather pathetic to say that there is only one true path to OS implementation. Why not admit that it is the only path that you have any experience in?
--exa--
I propose a new definition of "microkernel": If it's too big to fit in your CPU cache, or it has any sort of "network transparency" crap built into it, then it's monolithic kernel.
http://outcampaign.org/
I know as a good and faithful /.-ers we should worship Linus and take all of his words as gospel, but in this case I think he is talking out of his arse. Microkernels are "more secure" and "more stable" because only one component needs to work well -- the microkernel, it's main job is to enforce security policies and that is it. If it works correctly it will be able to bring the system to a certain state during the failure of any of the other components.
Microkernels are used and have been used for a long time in "real" and "serious" operating systems, not just toy examples. Everytime /.-ers fly over the Atlantic it is a microkernel OS in all probability that makes sure they don't crash and burn. The size of those microkernel is kept at no more than 10k lines -- and even so it can take years to prove its correctness. It would be impossible to do it with Linus's kernel. So if Linus and others are so against the microkernel acrhitectures I would want to see them trust their lives to a Linux 2.6 -- put their lives were their mouth (or code) is, so to speak.
I really don't know about the plane OS situation to say if I'd get on a plane flown by Linux, and the question is worded vaguely enough that I'd venture that I'd prefer a plane flown by human pilots over any OS, on account of the fact that I'm not sure that the A.I. is mature enough.
And I figure that most people are in the same boat.
I think the "microkernel vs monolithic" debate is a bit too close to implementation level. The real design question for me is whether an OS must have a deterministic behaviour or it can be allowed to have some uncertainty and side-effects (for example what happens if a service goes down). As Linus points out, in microkernel the desired effect is attained by combining the "simple parts". If you have dealt with distributed systems, you probably know that finding the suitable combination to create the desired results is a complex task and to make things even worse, the solution usually has some "unwanted emergent behaviour". In monolithic systems you can create control hierarchies to avoid such things, but in distributed system you have no good way of doing it.
To sum it up, I feel that OS must have a complete deterministic behaviour and this is not achievable with distributed algorithms. It's fine to build distributed systems from these deterministic building blocks on application layer, but OS really is one level lower.
I don't want to repost this old debate that I believe every geeks should have read it; but since nobody post it yet. I repost it for anybody who haven't read about this famous debate between Linus and Prof. Tanenbaum on microkernel.
Linus vs. Tanenbaum - "Linux is obsolete" Jan,1992
(Save your mod point for someone who really need them thanks!)
By writing it in C.
The high-level libraries and system servers (Not the same as a micro-kernel server!) are written in C++ The kernel is not.
would I want a kernel thread to run each core? So they pass messages to each other instead of doing something useful?
The analogy of centralisation vs. local autonomy is not totally accurate either. Both the monolithic and the microkernel are centralized, except that in the first case there a large beaurocratic structure and in the second case it just a dictator and a couple of "advisors". If the dictator or the king is chosen well, the system will be more predictable and will work much better. If case of the large beaurocratic system, if some of its members get corrupted [and they will because there are so many of them] the whole system will fail. It is like saying that a small bug in the mouse driver will freeze and crash the system with a monolithic kernel. Good thing if the system was only running Doom at the time and not controlling a reactor, or administering a drug. If the same happens in the microkernel system, the kernel will reload the driver, raise an alarm, or in general -- be able to take the system to a predictable predetermined state. Going back to the analogy is it is like having the dictator execute a corrupted staff member and replace him immediately.
Andy likes microkernels because they force you to do that. Time spent on design leads to insight, which may well point to better and cleaner ways to do the task you originally set out to acomplish.
Linus hates microkernels because they force you to do that. Time spent on design is time lost getting working code out the door, and working code will give you experience that will point to better and cleaner ways to do the task you originally set out to acomplish.
"I'd venture that I'd prefer a plane flown by human pilots over any OS, on account of the fact that I'm not sure that the A.I. is mature enough."
And which do you think is flying the plane when you are coming in for a landing and the fog is so thick you can't see the ground?
Individual pieces aren't really any simpler either. In fact, if you want your kernel to scale, to work well with lots of processes, you are going to run into a simple problem: multitasking.
This is very true.
Consider a filesystem driver in a monolithic kernel. If a dozen or so processes are all doing filesystem calls, then, assuming proper locking and in-kernel pre-emption, there's no problem - each process that executes the call enters kernel mode and starts executing the relevant kernel code immediately.
OK, here's where things start getting a little tricky. The whole locking setup in a monolithic kernel is pretty tricky. Early multi-processor kernels often took the course of "one big lock" at the top of the call stack - essentially only one process could be executing in the kernel. Why? Because all that "proper locking" is tricky. Took years to get this working right. Of course it's done now in Linux so you can take advantage of it, but it wasn't easy.
Now consider a microkernel. The filesystem driver is a separate server process. Executing a system call means sending a message to that server and waiting for an answer.
OK, now here, you're kind of running off the rails. What is a "message"? There is no magical processor construct called a "message" - it's something that the OS provides. How messages are implemented can vary quite a bit. What you're thinking of is a messaging system ala sockets - that is the message would be placed onto a queue and then a process switch would happen sometime and the server on the other end would read messages out of the queue and do something. That's how microkernels are usually presented conceptually so it tends to get stuck in peoples' heads.
However, messages can be implemented in other ways. For example, you could make a message be more like a procedure call - you create a new stack, swap your address table around, and then jump into the function in the "server". No need to instantiate threads in the "server" anymore than there is a need to instantiate threads within a monolithic kernel. The server would essentially share the thread of the caller. I've worked on microkernel architectures that were implemented just this way.
If the number of data structures that you can directly access is smaller, the amount of locking that you have to take into account is smaller. Modularity and protection makes most people's tasks easier.
Many of the arguments made for monolithic kernels are similar to the arguments you used to hear from Mac programmers who didn't want to admit that protected memory and multi-tasking were good things. Mac programmers liked to (as I used to say) "look in each other's underware". Programs rummaged about through system data structures and other apps data structures sometimes, changing things where they felt like it. This can be pretty fun sometimes and you can do some really spiffy things. However, set one byte the wrong way and the whole system comes crashing down.
Speaking as someone in Northern Ireland, I would suggest that the entire history of Ireland has demonstrated that proverb to be wrong.
TWW
"Encyclopedia" is to "Wikipedia" what "Library" is to "Some people at a bus stop"
The only way the monolithic vs microkernel debate will go away is if CPUs provide a better way of sharing resources between modules.
One solution to the problem is to use memory maps. Right now each process has its own address space, and that creates lots of problems. It would have been much better if each module had its own memory map, ala virtual memory, so as that the degree of sharing was defined by the O/S. Two modules could then see each other as if they belong to the same address space, but other modules would be inaccessible. In other words, each module should have its own unique view of the memory.
Of course the above is hard to implement, so there is another solution: the ring protection scheme of 80x86 should move down to paging level. Each page shall have its own ring number for read, write, and execute access. Code in page A could access code/data in page B only if the ring number of A is less than or equal to the ring number of B. That's a very easy to implement solution that would greatly enhance modularity of operating systems.
A third solution is to provide implicit segmentation. Right now 80x86 has an explicit segmentation model that forces inter-segment addresses to be 48 bits wide on 32-bit machines (32 bits for the target address and 16 bits for the segment id). The implicit segmentation model is to use a 32-bit flat addressing mode but load the segment from a table indexed by the destination address, as it is done with virtual memory. Each segment shall have a base address and a limit, as it is right now. If a 32-bit address falls within the current segment, then the instruction is executed, otherwise a new segment is loaded from the address and a security check is performed. This is also a very easy to implement solution that would provide better modularization of code without the problems associated with monolithic kernels.
There are various technical solutions that can be supported at CPU level that are not very complex and do not impose a big performance hit. These solutions must be adopted by CPU manufacturers if software is to be improved.
My carreer started in Operating System Research, this was circa 1993. Even in those days there were many people addressing the shared memory issue and coming up with good ways to share memory and address the context switch issue. However this took some overhead and did not make it to the mainstream because of that.
Today the CPUs are much faster and even sacrificing 10%-20% of CPU power is not considered too much if it results in a system that is (more) stable and easier to maintain. e.g. a device driver can no longer bring down the entire system and a spyware program can no longer sniff all keys pressed...
I must admit to have lost contact with that field of research but even the old results are promising, with today's CPU speeds.
So the question would still remain if you would get on a plane if someone tells you that it will be flown by Linux 2.6? I would personally trust my life to INTEGRITY-178B from Green Hills -- which does have a microkernel architecture, before I would trust my life to a huge monolithic blob of code such as the Linux kernel.
I am shocked that none of the crowed has even said one word about Linux not being a traditional monolithic kernel alltogether!
Traditional monolithic kernels used to be quite synchronous whereas the application in the end carries each activity and kernel activity is only carried out via syscalls or interrupts.
Now look at Linux which has become highly asynchronous, having kernel threads as means of activity on and for itself. There is a kthread for the journalled filesystem, for the kswapd, for the flushing of buffers, for soft-IRQs and so on. Which also means that SMP systems could execute application and kernel code on 2 seperate CPUs, completely decoupled and asynchronous - so the scaling argument FOR microkernels has effectively been killed by this design.
Linux is only monolithic by sharing the access space for all kernel components.
and even so it can take years to prove its correctness. It would be impossible to do it with Linus's kernel. I presume time or no formal spec but just out of interest why would it be impossible?
Who the hell is Linus Torvalds and why should I care what he has to say about kernal programming? Does he even have a degree in computer science?
And where do you spend most of your time executing in the BeOS kernel? The high-level libraries and the servers I would bet. The micro-kernel is probably implemented in C because C lets you get close to the hardware easier.
What's the problem with monoliths, that they are supposed to be less marketable? Ever since 1968, Monoliths have been doing great!
I'm in a Unix state of mind.
I write distributed apps that perform message passing.
Distribution is a horrendous model for an application that must share data often.
Cache coherency is a good example of why -- as you add more independent machines the load they incurr keeping each other up to date can quickly overtake any performance benefit you gain by having several machines.
This is why those high end scientific machines that require oft shared information across hundreds of machines use high speed (and expensive) machine interlinks.
Even then, they are carefully crafted to keep the sharing to a minimum.
Microkernels seem like a great idea in concept -- and I'm sure someone could pull it off. But they will almost certainly need to come up with some new paradigms and algorithms in the process.
All that aside, the entire argument really has reached the point of "show me the code". It has been tried (and failed) a few times now -- time to stop talking about it and do it if it is so easily possible.
But I'm willing to be corrected.
ian
First of all: I'm not a programmer.
How bad/good would be if a process could "give" some space to other process? Let's say process A wants to share some data with process B. Process A sends a message to process B ("do you accept my data?"), process B answers ("yes"/"no"/["wait"]). If the answer is yes process A tells the kernel to give the data "ownage" to process B. The kernel changes the owner. Process A stores who gave its data. When process A wants its data back sents another message to process B ("can you give me back my data?").
Can this work?
I would have guessed the pilots relying on sensors that tell them where important points of reference are.
Linux 2.6 has 6 million lines of code. Even assuming a linear increase (in reality it is exponential) it would take at least 600 years on the current hardware. If the time demands are exponential, you can forget it altogether
I don't place my trust in such things. If God wants me to do it, I do it...Physical 'reality' merely the stage for his will against the corruption he placed this world into.
Whether monolithic or microkernel, what it is expected from an OS is to manage resources, implement basic services et cetera in an effective and efficient way.
I think that the number of lines of code in either design direction tend to be almost the same, unless some code refactoring.
Also the number of "services" done by the OS tend to be the same.
Ease of maintenance, robustness, efficiency and so on are problems that should be faced in both cases with an overall need for resources that should be the same in both cases.
So, instead of debating, I'd do some real world tests, instrumentation and profiling in order to find out a reasonable solution. Being it shared memory or copy buffer, it really doesnt' matter.
Real effectivenes and afficiency do.
Prof. Tanenbaum and Dr. Torvalds (as well as a number of other people at their same level) have shown their deep knowledge in this area. A real advance in OS technology would be a constructive debate after the real world data analysis.
So the final question is: why not?
P.S. The referenced web site is still hot and smoking!
Maybe Computers will never be as intelligent as Humans.
For sure they won't ever become so stupid. [VR-1988]
Perhaps the best way to implement a microkernel is not to move as much as possible into userspace processes, but to move as much as possible into userspace libraries? A library call is synchronous, just like a system call, so writing a reentrant function for a library shouldn't be any harder than writing a reentrant function for a kernel.
The server could be multi-threaded, for example. But how many threads should it spawn ? And how much system resources are they going to waste ? A monolithic kernel has none of these problems.
A library has none of these problems either.
Of course you'd have to protect the library's state from the caller, which would involve a partial context switch when calling one of the library's functions - the 'call gate' would be one of the services provided by the microkernel. The protected library would have access to the caller's state, however, so it would be possible to pass a pointer to a data structure and have it filled in, for example, just like a normal library or monolithic kernel. A protected library call needn't be as expensive as an interprocess context switch, even for architectures without segment registers, because you'd only need to flush the TLB on the way out of the library call, not on the way in.
Anyway, that's enough armchair OS design for one morning... ;-)
Motorola's 68020 contained a "CALLM" command, call module, which was used for isolation of modules at a sub-MMU level.
Nobody ever used it, so it was discontinued in later processors.
But can I check my email and access the Internet Explorer?
"[Physics] has nothing to do directly with defending our country, except to make it worth defending." -- Robert Wilson
"..,but but to enforce a strict and precise security policy."
Precisely. All the arguments to date focus on performance issues, whereas with today's high-performance multi-core machines I'd be more than happy to lose a bit of performance if it means processes and systems have better isolation and protection from one another.
Gaining a couple of extra FPS's in Quake doesn't do much good if the entire system is down with a virus...
Any sect, cult, or religion will legislate its creed into law if it acquires the political power to do so.
I think a way to share data structures between multiple processes would be to allocate identical virtual addresses which could be determined by the processes themselves. Basically you would want to be able to allocate memory on user provided memory addresses, and then share it within the tasks that needs these addresses.
It could be implemented using a permission based scheme. Say you have 64 bit addresses. So you split it into 4 parts. One part of which must only be used for sharing addresses. You have a 30bit process ID, for each process a 32 bit address is provided. This address space can be used by other processes if they don't need to share the same address space transparently. In this case you can use pointers etc transparently. I know it still not as easy as working from the same address space. But you can work around the problem somewhat.
You can play MMU tricks, but for small amounts of data, it's faster to just copy. MMU operations don't have the same deeply-pipelined, out-of-order, multiple-instructions-per-cycle infrastructure that ALU operations and load/stores get. So on modern processors, the "small" data threshold below which it's cheaper to copy is more than 4096 bytes!
This, and similar other tricks, can certainly be done, but they're slower than copying.
Firstly, you are talking about two different scenarios, a plane, which is essentially an embedded system, and general purpose computing.
If (big if) Linux was used on a plane it would be a very different beast from what it is on your desktop.
For starters, a plane would not need 99% of the drivers that are included with the current 2.6 kernel.
Any drivers required for the plane would probably be custom written, as the hardware would not be your usual consumer level stuff, and therefore written to the appropriate coding standards for airbourne software.
Also the core of the Linux kernel would also have to be certified to airboure software standards (DO-178B), so to answer the question of 'Would you get on a plane that is flown by Linus' latest 2.6 monolithic kernel?' my answer would be only if it is certified to DO-178B.
The likelyhood of this being done is extremely remote in my opinion, so this is all speculation.
That's interesting because those are exactly my thoughts every time I hear the arguments people use to defend microkernels: Java is to microkernels as C/C++ is to monolithic kernels.
Linus Torvalds summed it well when he mentioned that microkernels are simpler only when data flow goes in one direction only. It's very hard to get a function to fill a complicated data structure for you if you cannot work with pointers. Passing a reference will do only for simple structures, it will not work if there are structures within structures, it is very hard to do if the called function must itself pass some subset of that structure to another function. And for operating systems where one must contend with multiple access and locking, it's almost impossible to do without a performance penalty.
Let's face it: pointer manipulation is necessary because there are real life problems that are more complex than textbook examples. If there weren't, inventing the C language wouldn't have been necessary, we could have stuck with Fortran all along.
Ok, so then I'll ask, "what are the chances that linux will be DO-178B certified?" And I'll make it easy and answer it for you too -- "Very close to 0."
Well maybe that's how *you* would design *your* Microkernel. And yes, it would suck.
The way I would design the filesystem driver, would be to accept a request, add it to a queue of pending requests to serve. If there are no initiated requests, find the request that can most efficiently be served based upon your preferred policy (closest seek time, for example, or first come first serve, your choice), and initiate that request. Add some smarts for multiple devices, so multiple requests can be initiated at the same time to different devices. When data comes back, answer the requesting process with their data. Rather than sitting around blocking on a request, go grab more requests from other processes and queue them up. No need to block. When an initiated request comes back, send back the data to the requesting process, and everyone's happy. Just because things are separated out into different processes, doesn't mean that they can't do some asynchronous juggling to be efficient. Add multi-threading, and the coding becomes a bit easier; but multi-threading isn't necessary to rely upon to have this work well.
I'm pretty sure the monolithic kernels do things somewhat similarly; build a request queue, service that queue. They could also block until they're done other requests, but that would be bad design. Don't assume a Microkernel Filesystem server has to suffer from similarly bad design.
Love many, trust a few, do harm to none.
Try reading the whole post first!
Individual pieces aren't really any simpler either. In fact, if you want your kernel to scale, to work well with lots of processes, you are going to run into a simple problem: multitasking.
This is true but only because threads are asynchronous. Linus and other OS writers may know Linux and Unix but they don't understand the hidden nature of software. If they did, they would know that basing software construction on the algorithm is the real reason for the current crisis. Switch to a signal-based, synchronous software model and the problem would disappear. Of course, in such an environment, every application becomes a simple extension of the system and there is no operating system per se.
We need to start seeing a program for what it really is, a communication system. During execution, every statement or instruction in an algorithmic procedure essentially sends a signal to the next statement, saying: 'I'm done, now it's your turn.' A statement should be seen as an elementary object having a single input and a single output. It waits for an input signal, does something, and then sends an output signal to the next object. Multiple objects are linked together to form a one-dimensional (single path) sequential chain. The problem is that, in an algorithm, communication is limited to only two objects at a time, a sender and a receiver. Consequently, even though there may be forks (conditional branches) along the way, a signal may only take one path at a time.
This is one of the main reasons that we need to move to a signal-based, synchronous software model. Monolithic or not, we have all missed the software boat. And we've been missing the boat for a long time, for more than 150 years in fact, ever since Lady Ada wrote the first table of instructions (i.e., algorithm) for Babbage's analytical engine. It's time to do it right and it's never too late to change.
Microkernels like Mach have been unsuccessful because putting everything into separate address spaces makes a lot of things quite difficult.
C-based monolithic kernels like Linux and UNIX run into software engineering problems--it gets harder and harder to ensure stability and robustness as the code mushrooms because there is no fault isolation.
The solution? Simple: get the best of both worlds through language-supported fault isolation (this can even be a pure compile-time mechanism, with no runtime overhead). It's not rocket science, it's been done many times before. You get all the fault isolation of microkernels and still everything can access anything else when it needs to, as long as the programmer just states what he is doing clearly.
C-based monolithic kernels were a detour caused by the UNIX operating system, an accident of history. UNIX has contributed enormously to information technology, but its choice of C as the programming language has been more a curse than a blessing.
I'd imagine one big reason for having pilots is in case you are forced to divert to somewhere that doesn't have the infrastructure for an automated landing.
note: i'm known as plugwash most places but i screwd up registering that here somehow in the past and now can't register
On microkernels, he's merely hand-waving like the rest of us.
The three US-based embedded real-time operating system vendors are all pursuing Common Citeria Certification at an EAL6+ level. To find more information on this, google the term MILS (Multiple Independent Levels of Security). The NSA, who is the only entity authorized to review the Development artifacts for US certifications at this level, has offered guidance: in order for a kernel to be evaluatable it should be in the nieghborbhood of 6000 lines of source code.
The problem is that inside a computer there aren't any "objects", only data. That's why, when you want the ultimate performance needed by an OS, plain old C will beat a purely object oriented approach.
The main issue raised by Torvalds is, how do you pass information among the different entities in a system? You either pass an address or you copy the data. It doesn't matter what that information is, it can be a simple string of characters or it can be a very complex object, in the end all becomes an array of bytes. Do you copy those bytes or do you send a pointer?
>Precisely. All the arguments to date focus on performance issues, whereas with today's
>high-performance multi-core machines I'd be more than happy to lose a bit of performance if it
>means processes and systems have better isolation and protection from one another.
When people go and by a new computer, many are willing to spend hundreds of dollars more to get a little extra performance. They will not like to have that taking away from them just so that they can run a microkernel.
>Gaining a couple of extra FPS's in Quake doesn't do much good if the entire system is down with a virus...
It is just a false premise, just because some monolithic (or hybrid) kernels are unreliable does not mean that it is necessary or better to use microkernels to get reliability.
I have used many Linux computers the last 10 years. They never went down with a virus, and I have not had problems with lack of protection between kernel drivers.
So I do not feel very motivated to give up performance.
"You can do simple things easily - and in particular, you can do things where the information only passes in one direction quite easily, but anythign else is much much harder, because there is no "shared state" (by design)."
Why is Linus ruling out the fact that shared state may be put in shared memory?
Considering that the most privileged user of a system will always need the ability to modify core parts of the OS, such as loading or modifying kernel drivers etc...
The first hurdle, is to ensure seperation higher up the chain before meddling with the kernel.
No matter how well compartmentalised your microkernel OS is, if your user runs all his apps as a privileged user and one of those apps becomes infected with a virus, it will still be able to work it's way down to any part of the core OS it chooses.
If an unprivileged user gets infected with a virus, it won't be able to trash the OS and the quickest dirtiest fix would be to logout, and log back in as a clean user.
http://spamdecoy.net - free throwaway anonymous email - avoid spam!
Proving the correctness of the core of the microkernel may be feasible, but I doubt it is even remotely possible for the "OS".
When there are hundreds of device drivers, each interacting with each other, and the fact that a lot of hardware out there have their own set of flaws and sometimes produce unpredictable behavior, the best bet would be to write code that is "as correct as you know it", and then test test and test.
Of course, on niche systems where the hardware can be controlled, proving it may be possible, but still if we're talking about mainstream OS'es like linux, the approach just wouldn't work.
"5 years from now everyone will be running free GNU on their 200 MIPS, 64M SPARCstation-5" - Andy Tanenbaum, in 30 Jan 1992
Any theoretical advantages those could have are obviously offset by some other facts not taken into account when developing the theory in the first place. If he is a true scientist and wants to deserve his title of University professor, Tanenbaum should go back and redo the theoretical aspects of his work and consider the reality.
Whilst microkernels are a lovely idea in theory, they don't deliver in practice. There is already a bottleneck between user space and kernel space and this will impact upon performance. No matter what you are trying to do, the slowest part of the process will always determine the maximum rate at which you can do it.
Monolithic, Linux/Netware-style modular and so-called hybrid kernels get around this limitation by moving things to the other side of the bottleneck. It makes sense on this basis to put a hardware driver in kernel space. You usually only pass "idealised" data to a driver; the driver generally has to pass a lot more to the device because it isn't ideal. For example, when talking to a filesystem driver, you generally only want to send it the data to stick into some file. The filesystem driver has to do all the donkey work of shunting the heads back and forth and waiting for the right spot of disc to pass under them.
It might be "beautiful" to have as little code as possible situated on one side of the division, but it's most practical to have as little data as possible having to travel through the division.
Je fume. Tu fumes. Nous fûmes!
This argument has been hashed and rehashed so many times. Why not write the linux kernel in assember to improve performance? Its the same argument... It could be done but its a big waste of time. Move on.
The kernel is becoming too big, and some parts of it (think: hamradio, USB gadgets
I am still craving for the day when Linus will define a "kernel ABI" for driver modules, and some parts of the kernel source will get kicked out of the
I believe this day will come; and there are good reason to believe it
-
suppose FOSS dream comes true, and linux ever become the mainstream desktop OS, and every vendor supplies FOSS drivers for their hw.... it will not make sense to ship any single gadget/protocol driver in the same
.tar.bz2
- even today, it does not make sense to ship drivers forever, for hw that is now unavailable to buy; but at the same time it would be unfair to
just drop the code to people who still own that hw.
- having 220MB of source code without a published and enforced ABI for modules means that any change to some parts of the kernel, such as memory management, force almost everybody to rewrite their code ; this, in the long term, may foster innovation. It would be much better if there were some stable ABIs for drivers for lesser demanding drivers (such as webcams).
Summarizing, IMHO the current monolithic situation cannot scale up forever."IOS XR is not based on their widely deployed IOS operating system, and is instead based on the QNX real-time operating system."
http://en.wikipedia.org/wiki/IOS-XR
"Cisco IOS XR Software, a new member of the Cisco IOS family, is a unique self-healing and self-defending operating system designed for always on operation while scaling system capacity up to 92Tbps. Cisco IOS XR powers the Cisco Carrier Routing System, enabling the foundation for network and service convergence today while providing investment protection for decades to come."
http://www.cisco.com/en/US/products/ps5845/
>> In other words, it's the language.
...}, and despite willful attempts at livelock chasing and deadlock triggering.
Not really, no. It's the interactions architecture, which is more fundamental.
You can quite easily create fully thread-safe and hardware parallel-safe interaction structures on any system and make them available through opaque, MMU-protected APIs which are then accessible from simple/primitive languages like C without any danger whatsoever. Even in the face of {fork(); run(); fork(); run();
The language is not the problem, as long as it is not used beyond its inherent capabilities and design constraints.
Your statement that "It's the language" implicitly presupposes that complex solutions have to be designed with threaded programs, but that's very far from the truth. Indeed, to some extent it's that very premise that has got current computing into the flakey mess that it's sometimes in.
As a systems and language designer who has been working with parallel systems throughout a very long career, I am appalled that people are still trying to use solutions that were invalidated on theoretical grounds 4 decades ago. Shared address spaces and threading belong to those invalidated methods.
You are right about the non-existence of a mainstream computer language that does threading "right", but even if there was, it would just be dealing with the symptoms rather than the disease.
"The question of whether machines can think is no more interesting than [] whether submarines can swim" - Dijkstra
Here's my thought to the discussion. Just how much would hardware contribute to the decision to go with either one? And I'm not just talking about raw speed, but capabilities. CPU's already support threads, and virtualization. What else could be added to make microkernels more viable?
Only a really, *really* incompetent idiot would write such a server which blocked until the read was finished.
This sounds like a veiled reference to something; would you care to name it?
"Sometimes the truth is stupid." - Lawrence, creator of Prime Intellect
It really isn't specific to operating system kernel design. It applies to all orgnisational structures which are assembled to perform actions, from computers to businesses and biology.
Speed and efficiency vs distributed modularity and security. Which is most appropriate depends on the environment, there's no one true right or wrong answer.
Deleted
Here is my 2 cents.. First of all deciding what kernel is better technically has nothing to do with its popularity. [ Windows anyone ??? ]. The question is What is actually better given the current hardware standards. This argument is going on for ever, and maybe monolithic won the argument 10 year ago - But that does not definately mean that those argument stands today the same way it did then. Computer Science, both hardware and software has come a long way since then. Maybe this is a good time that Andy has decided to start this up again. Not that anything is majorly wrong with linux kernel right now and its in best shape it has ever been in, but I think this is a good time to for linux buffs to compare their whole ideology to a competing one. Not with a view to achieve a grass root level change in the kernel, but as a excersie of self examination. See whats going wrong, and if there is something that is going wrong try and solve it. It would be very foolish to ignore any opposing aruguments and stick to good old dogma. I personally took a class for both Minix and Linux (Kernel programming), so I have come to appreciate both of them. And when i read arguments, both side seems right. I hope this is the hint..
http://en.wikipedia.org/wiki/IOS-XR
http://www.cisco.com/en/US/products/ps5845/
"Cisco IOS XR Software, a new member of the Cisco IOS family, is a unique self-healing and self-defending operating system designed for always on operation while scaling system capacity up to 92Tbps. Cisco IOS XR powers the Cisco Carrier Routing System, enabling the foundation for network and service convergence today while providing investment protection for decades to come."
Good coding practice to stop exactly that bug.
Unless you're really sure that you never do typos.
Wikileaks, no DNS
We call them eyeballs.
Whenever this issue comes up, I swear to myself that proponents of microkernel architectures created the term which they use to address their opponent. The terms used to discuss this are heavily loaded. “Microkernel” sounds lean, quick, and simple, while by subjective contrast “monolithic” sounds bulky, old, and unwieldy. I think that when engaging in this debate, it is best that we prefer to at least use “unified kernel” in place of “monolithic”, being it is more accurate and contrasts with “microkernel” objectively. The term most people use for kernels like Linux and NT seems to imply that there is no logical separation of components and that all pieces are somehow a gigantic (dare I say monolithic) glob and that is nonsense.
Join Tor today!
I think you missed it. He says that the calling process has to block, not the filesystem server. Your model does the same thing. A process calls for a read and waits for a response. It doesn't know what the filesystem server is doing so it just keeps waiting. That is called blocking. If you don't want your process to block then you need to make another thread that would make the read request. Then you would have that thread block (again, in either model) and the rest of your process could keep running.
A monolithic model would technically not be blocking because the same thread that makes the call for a read does the read. Both monolithic and micro models block for the hardware. The micro also blocks to change execution from one process to another.
Take another gander at what Linus was saying in the GP post. Address-space tricks don't address his issues.
Patrick Doyle
I mod down every jackass who puts his moderation policy in his sig. Oh, wait a sec....
And anybody who tells you that distributed algorithms are "simpler" is just so full of sh*t that it's not even funny.
And anybody who tells you that it's possible to have deadlock-free code in any software of reasonable complexity that uses shared state concurrency is similarly full of sh*t. Fact is, creating deadlock-free code is harder than solving distributed problems; unfortunately, people have trouble accepting this.
The whole "microkernels are simpler" argument is just bull, and it is clearly shown to be bull by the fact that whenever you compare the speed of development of a microkernel and a traditional kernel, the traditional kernel wins. By a huge amount, too.
And traditional monolithic kernels are buggy, and unreliable. This too has been proven time and time again. The important question is: what's more important to you, development speed, or reliability?
Higher Logics: where programming meets science.
While autoland systems are used overseas, I do not believe they are used in the U.S (but they probably will be someday).
While the technology may be available to allow pilots to do very little, that's not how it's done in practice. The last 3 times I flew jump seat (Dash-8, CRJ, Boeing-777) most of the flying was hand flying, with the exception of the cruise portion of the flight. The safest system is probably the track that we are on: automation to do the boring parts, and a wealth of information presented by computer to the pilot in a way humans can easily interpret (so, for instance a HUD with computer synthesized imagery so the human can see through fog, night, etc.).
And, to answer your question about kernels, I'd feel fine with Linux if it passed DO-178B Level A certification, but that's probably not going to happen anytime soon ;-)
>> Only a really, *really* incompetent idiot would write such a server which blocked until the read was finished.
> "This sounds like a veiled reference to something; would you care to name it?
Minix
Actually, this isn't the way most moderm microkernels work either. Generally, you talk to a THREAD associated with the driver. This thread adopts the callers slot and priority in the run queue temporarily, and scrutinizes the caller's request (performing roughly the analysis that you suggested, but at the appropriate priority, which might be much lower than some other process that wants the same driver a fraction of a milisecond later).
The request is then either carried out in the handler thread, or passed off to a centralized driver thread after triage.
This *is* more complex (which is Torvalds' point), but it's not horrible. Most of it can be wrapped in macros/templates/whatever and is uniform across all drivers.
I think that Tovalds makes some excellent points, and simplistic arguments like "microkernels are more secure because each part is smaller and simpler," are just that: simplistic. Overly so.
Still, there's value in the microkernel approach, as has been repeatedly shown. I'll remind readers that microkernel's don't all look alike. Most functioning microkernels are hybridized in one way or another with monolithic kernels to achieve usability. In the case of MacOS/X, that involves placing a monolithic kernel on top of the microkernel as a subsystem. In the case of NT/XP/Vista, that involves re-writing the most performance- and security-sensitive subsystems as monolithic subsystems (and, shockingly the NT kernel is about the only place that NT gets security right).
Microkernels are here to stay, as they offer some useful abstractions, but I don't think that they harken the doom of monolithic kernels like Linux. It's just a different approach.
At the end of the day you're going to end up with a hell of a lot more documentation and proofs that no one will ever read, and the system won't be much better than the system that wasn't proven.
Actually, I am not interested in proving the kernal correct, no one is in the real world (imo). I am interested in being assured that my PROCESSING is correct. While the micro kernel may be smaller (not equal to simpler) I still need to then look at all the services that the mono kernel supplied that are external to the micro kernel.
...) is a completely different animal. No one size fits all (shocking I know).
In all cases where a general computing OS is used the services list is probably the same (custom kernels are a different matter and a micro may strip down better, or not).
Yes you get SOME advantage in security as MAYBE less things run at ring 0 but still lots of stuff will run at elevated priviledge (ring 0 or 1 not 3) and you have more complexity.
In my opinion performance is one thing you care about, maybe less than security but you care. If the end-to-end security issues are even roughly the same between mono and micro kernels then performance trade-offs start to weigh in more (if I can have 1% better security at a 50% performance loss, do I want the trade? Where is the swap point, 5% security and 25% performance, 10 to 10, 50% better security at a 1% performance hit?). Oh, and yes the brighter reader is correct, it depends on my usage, does is not?
Micro kernel OSs are more complex end-to-end. More complex typically implies more code, more code typically implies more potential bugs. However, microkernels are more compartmentalized, better compartmentalization improves security (broken part A does not imply access to part B). So the intended usage of the kernel impacts its overall end-to-end security 'rating' for the application in comparison to a mono kernel.
A system that is only used by a single user, no network access, physical access restricted, user always runs a root, is probably as secure in either case (and a damn rare bird). A system that is naked on the net running 50 different publicly accessable services (web, DNS, mail, IM,
Life is full of trade-offs, this is just another one.
Be had a strict "no C++ in the kernel" rule. Yet another example of the epic amount of misunderstanding and bullshit that still surrounds BeOS to this day. And I say that as a huge fan of BeOS.
administrational information paths leverage synergies and increase the efficiency of profit centers extrema organisational paths...
*makes retching noise*
If you must!
Linus is a good programmer. But to think he is the ultimate expert in OS design isn't even logical.
Most of the current Linux kernel wasn't written by Linus. It was written by many experts each submitting code to Linus.
Then let's talk about innovation? Linus started with what he had learned from Minix and Unix and wrote his own kernel for the i386. He was daring in making the jump that he could write a unix kernel. He didn't do much in the design of Linux that was innovative.
BTW I am not saying he copied Minix. I am saying he learned from it which is what it was for. If I remember correctly he did his first builds of Linux using Minix.
To elevate Linus to a the position of the all knowing God of OS design is at best unfair.
The idea that Linux is the ultimate OS is also very flawed.
It may be that the very idea of one kernel for everything from a wireless access point to a super computer is just flawed.
The next generation of computers may use a very different cpu architecture than the current X86. Look at the Sun T1 and the IBM Cell chips.
Maybe in the future we will have system that use many cores and many different types of cores. You could have several in order risc cores that run simple utility tasks along with several out of order cores that run more complex branching style tasks, and several FPU/Vector units doing number crunching. For such a machine a monolithic kernel might be a very bad answer.
I really hate this we have Unix and we nothing new mentality.
See my blog http://ilovecookes.blogspot.com/ for light hearted technical information.
The problem is that it doesn't match the way most people work right now.
Check out this brilliant paper by Alistair Cockburn (spoken as Co-burn) - Characterizing People as Non-Linear, First-Order Components in Software Development. Over and over in this paper he says:
- Problem 1. The people on the projects were not interested in learning our system.
- Problem 2. They were successfully able to ignore us, and were still delivering software, anyway.
Alistair comes to an equally brilliant conclusion: In short, without Linus, microkernels may help. With Linus, a monolithic kernel works fine.If you've ever worked on a software project with more than four people, didn't the personality and skills of the people involved make more of a difference than any methodology, abstraction, or even the language used? That's always been true in my experience.
Shae Erisson - ScannedInAvian.com
I would personally trust my life to INTEGRITY-178B [mil-embedded.com]from Green Hills -- which does have a microkernel architecture, before I would trust my life to a huge monolithic blob of code such as the Linux kernel.
But can that "Integrity" play DVD while transfering data intensively through several protocols at once (e.g. SMB, NFS etc), is it able to run F.E.A.R or Quake at decent framerate and how much does it cost ?
You are comparing apples to oranges. Flight approved gear has to meet very different requirements and raw CPU horsepower usually isn't one of them.
Sure, they might have to have deterministic response time, but OTOH they do run in a very controlled environment. You probably can't just log in from pilot's seat and install fresh DivX player on it...
I'd LOVE to se that "Integrity" of yours running Gentoo and a pilot with the balls of steel, doing "emerge --sync ; emerge -uD world" before each flight.
The Smalltalk 80 system was an OS, GUI, programming environment &etc. in Smalltalk, using a VM, with complete OOP orientation.
And, yes, there was an OS, and it was run on the VM, and no-one seemed to mind.
Squeak is the descendent of that work. Its portable because the VM can be moved -- the actual Smalltalk code uses the "OS in Smalltalk". Its probably the environment you want for your OS concept exploration.
Ratboy.
Just another "Cubible(sic) Joe" 2 17 3061
"Arguably it's not really relevant either. "proving" a software program only proves that the programs conforms to the spec. Now who proves the spec? And who proves the proof?"
Specifications are often simpler than programs. As a pedagogical example, the notions of "ordered" and "permutation" are simpler to express than the code for most sorting algorithms.
In the case of operating systems, you might not even be interested in total correctness. For example, you might only try to prove something like "every process eventually gets a chance to run", instead of trying to show that they all run in some particular order.
As far as who proves the proof goes, I suppose you could have humans look at it. But probably it's more useful to write a tool. All programmers are used to working with type systems now, and your type checker is really a very simple theorem prover. More general purpose provers, such as ACL2, HOL, COQ, and PVS, can also be used to check proofs, so that not many humans need to read or understand them.
You might find it useful to think of proofs as "really good test suites" that are able to check some property not just on a few random cases, but on an infinity of cases. They may certainly take a lot more expertise and effort to set up than your typical regression suite, but they can be a lot more comprehensive, through the awesome power of induction and symbolic reasoning to reduce the infinite to the finite.
Lastly, speaking from experience, the process of proving code correct often reveals lots of hard to find bugs. Maybe they could be found in other ways, but maybe not.
It seems to me that the argument over a micro vs monolithic kernel comes down to what people expect from Linux. The micro is oviously the choice for security, but as we can see there are some complications to it that make it more difficult to develop. On the other hand, it is much faster to develop in a monolithic kernel, which is what most of the market demands. Why not fork the kernel and start down a path of micro vs monolithic. the micro could be geared towards high security and embedded systems, while the monolithic could be geared towards desktop and the general consumer market. Of course the trick is to make sure both kernels run the same code, which is no easy task, especially if the micro is behind in development.
When people go and by a new computer, many are willing to spend hundreds of dollars more to get a little extra performance. They will not like to have that taking away from them just so that they can run a microkernel.
These people are really not the kind of people who are going to use microkernels, or really care that much about stability. Home users, in general, appear pretty far down the "stability/performance" tradeoff scale, towards the performance end. The advantage for them to use a microkernel, or any other architecture which trades performance for increased stability, may be minimal.
But then again, they're not really the market for high-reliability systems: real time systems, command-and-control applications, and embedded systems are. Increasingly, servers are going to fall into this category as well.
I have used many Linux computers the last 10 years. They never went down with a virus, and I have not had problems with lack of protection between kernel drivers.
This is a straw man. I'm sure somebody out there is willing to pipe up and say that they've used an unpatched Windows ME box for some obscene length of time, but we all know it's insecure. Likewise, just because you've never seen a Linux box go down doesn't mean they're immune, or that if you were designing a system that needed "five nines" reliability, that you'd have a basis for making a selection. The point of a microkernel, as someone further up in the thread (GP?) said, is that it's easier to analyze the code and prove, to an acceptable degree, that it is secure and stable. The fact that a server has run for a year or 10 without crashing isn't enough; you need to be able to demonstrate basically a priori that the system will be reliable, in addition to having test cases.
So anyway, in a limited way I'm agreeing with you. Joe Blow the 3D gamer probably isn't going to give a crap about microkernels, and isn't going to find their advantages convincing. But someone running any kind of production server might, and certainly anyone building high-reliability or embedded equipment should.
The question then becomes: which group of people is Linux being built for? Where, on the performance versus stability continuum does it reside?
"Ladies and gentlemen, my killbot features Lotus Notes and a machine gun. It is the finest available."
When people go and by a new computer, many are willing to spend hundreds of dollars more to get a little extra performance. They will not like to have that taking away from them just so that they can run a microkernel.
Agreed, but these are the same people who don't really care if they're at the bleeding edge of technology and have to deal with super-l33t video driver 0.8.2b crashing every so often.
It is just a false premise, just because some monolithic (or hybrid) kernels are unreliable does not mean that it is necessary or better to use microkernels to get reliability.
I'm afraid the false assumption has fallen upon you here. It's proven, time and again, that microkernels make it simpler to guarantee security and reliability. Yes, microkernels hurt performance a bit. However, it's throwing the baby out with the bathwater to discard microkernel architecture because of performance. By discarding microkernel architecture, you also discard the architectural segregation of system services, which makes for a very simple way to segragate effort when you've got say, an open-source project with developers located around the globe. Microkernels also ease maintenance, again, because the kernel remains small.
A HUGE misstep that the monolithic kernel camp has made by pointing fingers at microkernels' performance is this: smart coders write good, clean, testable, reliable, secure programs first, and optimize later. One should never, EVER attempt to optimize code on the first pass. Write it, test it, fix it, THEN optimize it. Leave the clearly non-optimal code in during the first few passes, just for the sake of maintenance. Then, you'll have a good, clean codebase from which to begin profiling and optimizing.
I can personally testify to spending exorbitant amounts of time debugging architecturally un-sound code, written intentionally so, because a wise architectural decision would've resulted in lesser performance. Out of curiosity, I usually run profilers over this code. Most often, these architectural decisions result in such a negligible performance increase that it pales in comparison to the maintenance nightmare that ensues from it.
There's nothing magical about microkernels that prevents them from being optimized, just like any other program. The benefits of the microkernel architecture certainly outweigh the performance hit in my book.
I recommend sodium chloride (5mg) if you disagree with any of the above.
I pity the foo that isn't metasyntactic
Sooooo, it's easy to have someone else handle the multi-process bits in a monolithic design. But when it comes to writing services for microkernels suddenly everyone is an idiot? I don't think that was what was meant. Thing is, with a monolithic kernel every process can run in userspace or in kernel space. (OK, I'm assuming a 1:1 kernel threads to user threads, but lets ignore that issue for now) Because all the processes have a kernel context, it's quite simple to manage multiple processes making use of the kernel at once. Run kernel code to service the filesystem request in the kernel-mode context of the process that made the request. At this point, if the kernel supports pre-emption then it's possible to pre-empt that process during kernel-mode execution and resume it later. In a microkernel you don't get that. The filesystem server doesn't implicitly get its multithreading from each process being represented by a kernel thread - because it can't access the kernel. If it wants an implementation of multithreading it has to implement its own (nb. could use a library to simplify this). But lots of tasks now require explicit extra code: the FS server might need to handle scheduling priorities itself, because the internals of the server aren't under direct control of the kernel; threading in the FS server must be made explicit because it doesn't come "for free" when processes are created. This is a problem for every server that needs to serve multiple clients simultaneously. A lot of this should be solvable with library code, I have thought. But the basic argument here (AFAIK) is that you have to code up somewhere in userspace extra implementations to take care of things that are implicitly provided for in a monolithic design.
Taking the utopian view, keeping things strictly isolated makes them provable. Everything. Your video driver can now be proven in the context of its defined interaction, instead of in a messy process space. Maybe in the near future, we'll have intelligent systems strong enough to do the following:
Right now, proving code isn't just very hard -- it's very, very hard because there's always the possibility that some useful, correct technique or transformation hasn't been formalized yet. But by keeping everything compartmentalized, each member becomes verifiable. Nobody is going to run independent tests on source with their own hardware because of the immense complexity, although I look forward to a day when we might verify the correctness of source code as easily as we check MD5 sums today.
By clearly defining acceptable inputs and outputs, and with enough computing power, we should be able to enforce correctness at least in terms of security and stability, if not suitability for a particular task. The video driver might still draw a few wrong pixels, but we will know that it won't draw them outside of its address space, or return a function pointer with corrupted data. I think, though, that this is acceptable. Formal algorithms and approaches tend to be much easier to confirm than their implementations.
Jasin NataelTrue science means that when you re-evaluate the evidence, you re-evaluate your faith.
Now consider a microkernel. The filesystem driver is a separate server process. Executing a system call means sending a message to that server and waiting for an answer. Now, what happens if the server is already executing another call ? The calling process blocks, possibly for a long time if there's lots of other requests queued up.
Well maybe that's how *you* would design *your* Microkernel. And yes, it would suck.
He's right. That's how microkernels work. There is no opportunity for concurrent processing with a microkernel. Too bad, they seemed like a good idea.
Having lately been coding Interprocess communication structures, I think Linus nails the issue. The solution to this it seems to me is very simple in concept. We need something akin to a parallel socket connection. As it is stands copying memory, as one does with serial scoket communication, is the bottleneck in any message passing communication between processes.
Now one way to look at this is that serial communicaiton, like copying, is effectively like have one byte of shared memory between two processes. To transfer a data straucture you effectively have to serialize it across this one byte. You do have locking bewteen the processes, only its just on the one byte (the last byte copied or the last byte serialized). So it's not locking on the data structure which is the problem.
So the solution to this is to have a page of shared memory. Lots of bytes. and locking on this page.
One still has message passing and isolated processes since they are only sharing that page not their stacks or registers, or anything else.
I like to call this a parallel socket. But whatever it's called, if you implemented it, it would bridge the world of micro and monolithic kernels. And it would allow you to acrue all the advantages of micro kernels with only a slight weakinging of their isolation.
Some drink at the fountain of knowledge. Others just gargle.
Better make that: you swap your address table around, create a new stack, and then jump into the function in the "server". Otherwise your new stack isn't in your address space, while is going to be a problem. In any case, a bunch of the work of creating a new thread is creating an additional stack in an address space that already has stuff in it. You have to make sure that the address range you're going to use for it isn't in use as a stack already, and isn't being concurrently allocated as a stack on a different processor, which requires the microkernel to do a bit of clever locking.
Then, of course, you're writing a filesystem driver which is concurrently handling multiple requests that may involve the same data structures, so you need all the same fancy locking that a monolithic kernel would need.
Fundamentally, if you care about scalability, you need locking for managing your resources, regardless of whether you have a microkernel or a monolithic one, because the on-disk data structures are a shared resource. If you one a microkernel, you additionally have the driver's address space as a shared resource that needs to be managed (and this could have a lot of contention if, for example, you have a lot of processes simultaneously opening different files in the same filesystem, where all of the data is already cached in memory). With this, you reduce the chance that code outside of your driver but inside the kernel could write to your driver's address space, which isn't, in practice, a common occurance, because other code generally won't have pointers that go there.
Umm, doesn't that mean while you've prooved that the 10k microkernel lines correct, you'd still have ~6 million lines of code sitting outside the microkernal waiting to be prooved? I can't see how a microkernel can magically do with 10k everything Linux is doing with 6 million lines (especially as by the definition of microkernel, than there's no way it could).
If the majority of the system services are implemented by one "server" or "module" with ~6m LOC, then you're missing the point of a microkernel anyway. In a properly-implemented microkernel system, those 6m LOC would be split into well-defined, easily-provable chunks. As the LOC increases, it becomes exponentially harder to prove the code's correctness. As an example, let's consider the "index of provability" to be 2^LOC (an exponential expression). So, proving a 6m LOC kernel would be:
2^6e6 (a number requiring six million binary digits to express)
Now, let's consider breaking that 6m LOC kernel into 20k chunks. Each chunk would be 2^20k, and there would be 300 chunks. So, the index of provability for the microkernel would be:
300 * 2^2e4 = 2^2.0002e4 * 3 * 5^2 (a number requiring 2.0009e4 binary digits to express)
The latter is MUCH smaller. Breaking the system down into smaller chunks helps provability a LOT.
I pity the foo that isn't metasyntactic
Monolithic....micro.....hybrid.......
To the extent that I understand kernel architecture, what Linus says makes a lot of sense. But this bit worries me:
The whole "microkernels are simpler" argument is just bull, and it is clearly shown to be bull by the fact that whenever you compare the speed of development of a microkernel and a traditional kernel, the traditional kernel wins. By a huge amount, too.
This confuses simple with easy, and they're two very different things. For example, a copy-and-paste coder takes the easy path, whereas somebody who abstracts out the common functionality is pursuing simplicity. Linus may be right about the point, but the argument itself is bunk.
The problem with that is that most of your accesses are going to be to data cached in memory, which can be handled immediately (or, at least, as fast as the context switches). In order to be efficient, you need to be able to handle multiple of these calls concurrently, if they don't conflict, on different processors.
What you can do is have the kernel handle the non-driver-specific stuff (i.e., cached directory structure and cached file data), since that's essentially a generic facility like allocating physical memory to address spaces. The driver only gets called for stuff that's specific to the filesystem, which is going to require disk access (which is slow and serial) anyway. The generic facility doesn't get protection from other internal generic facilities, but it's relatively small and doesn't have many special cases, so it gets tested effectively.
Of course, such a design is already available, in Linux, with FUSE. So Linus evidently didn't argue against it effective, if at all...
(Of course, some things are still tricky; how do you deal with drivers in userspace which may need to allocate memory in order to handle writes, when the writes may be triggered because data has to be written out to free up dirty buffers, and the memory management system has no clue how much memory the driver could need?)
frighteningly, i've never heard a better argument for fascism. Oh, except I guess it would require humanity to be running different software.
Folks, this has been said before, but bears repeating. Microkernels vs. monolithic kernels is a valid debate, but not *the* debate. Instead of allowing arbitrary binary code, and trying to figure out how to build complicated tricks to verify that it does not break security, we should be working on an operating system based on a virtual machine with a high level bytecode, a JIT, and a bytecode verifier to ensure that only code with predictable semantics is allowed to execute. With such an OS, the whole thing could run in supervisor mode with no traps at all, thus offsetting whatever performance is lost due to the bytecode execution (which I think would be minimal anyway since we have really good JITs these days).
What you're talking about is very close to CPS.
There are some ways to convert normal function calls to CPS.
And there is something called monads used to convert imperative algorithms to functional style.
And yes, continuations can be a very powerful technique.
However, CPS functional code is still coding an algorithm. Any way to compute something is an algorithm. May be you should name your critic "I dislike imperative algorithms, and I like CPS functional algorithms."
We are Turing O-Machines. The Oracle is out there.
It would have had a kernel, but it'd been a separate dictionary running a background process. A good example of what I'm talking about would be MVP Forth running on x86 PC's- it was multithreaded back in the early 80's and you could use it as a full-blown OS environment if you wanted to. You probably could tickle an OS layer in F-Code out of OpenBoot/SunBoot if you tried hard enough.
I am not merely a "consumer" or a "taxpayer". I am a Citizen of the State of Texas
==
So anyway, in a limited way I'm agreeing with you. Joe Blow the 3D gamer probably isn't going to give a crap about microkernels, and isn't going to find their advantages convincing. But someone running any kind of production server might, and certainly anyone building high-reliability or embedded equipment should.
==
Yes, I was talking about home users because the parent talked about viruses and FPS in quake. If you play Quake and your computer get viruses, Linux is the obvious way to go.
Viruses is not a problem on decent real-time embedded systems, microkernel based or not.
> Likewise, just because you've never seen a Linux box go down doesn't mean they're immune
No, just as microkernel bases systems are also not immune.
==
The question then becomes: which group of people is Linux being built for? Where, on the performance versus stability continuum does it reside?
==
If it is a continuum.
"Why split fundemental os functions, such as memory management, into user
p pa.html
processes? As all good *nix gurus know, the means to success is to
divide and conquer, with the goal being to *simplify* the problem into
managable, well defined components. If splitting basic parts of the
operating system into user space processes complicates the function by
introducing additional mechanisms (message passing, complicated signals),
have we met the objective of simplifying the design and implementation?"
He had said the same thing in the last flame-war, which means exactly the same thing which Linus is saying now.
The main point is that the simplest design is the best design.
A microkernel is not the simplest possible design, a monolithic kernel with proper modularisation is simpler.
http://www.oreilly.com/catalog/opensources/book/a
First up I helped develop a Linux USB webcam driver. These things can sometimes push a serious amount of data about the place and the camera won't wait for you before sending more. Being at the mercy of scheduler because the decoding is in userspace could well mean performance is poor (where I was bayer decoding was done in kernel precisely for speed concerns). The other thing is that if the USB driver is in the kernel the output can be exposed as a video device rather than forcing each program to implement each camera's USB dialect. If you want to use established video playing software this last point is fairly key.
As for stable kernel ABIs... they will only make things worse as fewer people are able to debug your problem. The only people who have the resources to cope with support for a binary driver platform (which are the only winners from a fixed ABI) for hardware with as many permuations as your typical PC are Microsoft (and on Windows people even circumvent measure designed to improve drivers). You need more not fewer people as the amount of hardware possiblities go up and a kernel ABI actively discourages this.
Having to keep even the kernel API stable only encourages resistance to change and layers of glue in the kernel in an attempt to keep old binary drivers working (thus hurting future developments).
As for the space requirements for shipping all those drivers... quite frankly they are negligble compared to the size of disks in your modern desktop computer. Saving even 500Mbytes of hard disk is probably a false economy when your typical disk size goes over 50Gbytes.
Seems it was a very close call indeed.
Remember 386BSD? Here's this article "The unknown hackers on Salon quoting Linus saying:
As far as I know, 386BSD was in fact available before Linus made his first release.
The Hacker's Guide To The Kernel: Don't panic()!
IBM is shipping it. Novell, RedHat, WindRiver, LinuxWorks, Motorola, Sharp, Sony, Hell even I'm shipping it in embedded products. It is easy to "prove it works" as alluded to in another post.
Microkernels are also shipping from QNX and, uh and, oh I'm sure there are a few more. (Not knocking QNX, considered it but tossed it, due to cost and liscensing.)
Is one more secure or stable than another, is really the wrong question.
The question is really is the "System" designed with microkernel more or less stable or secure or functional then the alternative.
I think it has, to my satisfaction, been settled. From RevolutionOS the movie (BuyIt!) Stallman is asked why HURD is so far behind Linux. His answer, (paraphrased, sorry RMS) Turns out a microkernel is very difficult to pull off because of the constant stream of messages required for the simplest of tasks. This forced ovehead only makes the Kernel more secure not the system, if the "drivers" keep crashing out and restarting you could go months without noticing critical flaws. "But the kernel is rock solid" doesn't really help if I can't ship the "System", does it. The only evidence you need, is the development pace of Hurd or even QNX to show this.
I respect the professor and his work, but it was an inspiration for a much more scalable design that clearly is superior for the rapid development a modern OS is expected to have.
As an engineer I see the beauty, but as a Production Engineer I can also see the added complexity a microkernel brings.
Of course you could, argue theoretically that I'm wrong or prove it by making a GNU/Minix distribution to compete in the real world with Linux. Almost 15yrs and a flood of Students haven't helped Professor T, produce it yet. Admittedly not his goal, but come on I know students and CompSci students have a knack for carrying their favorite teacher/classes with them throughout their career and it shows up in their projects.
OSGGFG - Open Source Gamers Guide to Free Games
And what happens when the queues fill up? That's when things get interesting... (avoidance of deadlock, etc, etc)
Couldn't a program be "blocked" trying to issue a request when the queue is full and at the same time, it wouldn't be able to accept the "Reply" from a previous request do to this?
Sounds like a resource-based deadlock even though the requests themselves do not create deadlock.
Congratulations, you've just reinvented monolithic kernel ;). Linux kernel really is just a bunch of library routines, some of which can be called by userspace programs and some by interrupts, and some setup code to set up the initial page tables, hook certain routines to run when certain interrupts are raised, and execute /sbin/init.
Forget magic. Any technology distinguishable from divine power is insufficiently advanced.
My point is that a formal proving process is not necessarily better than an ad-hoc code verification process in the respect that just because you can (using a tool, which we for argument's sake can assume to be bug-free) prove that your program conforms to a formally written specification doesn't mean that the code will work. All you have proved is that it conforms to the specification. You simply moved the potential for bugs from the implementation to the formal specification. The problem is that the formal specification is just as or even more complicated to read and write than the implementation itself. Not to mention the fact that very few people know how to express software designs in a mathematical notation rather than code, and even fewer people a actually prefer that notation to normal computer code.
I think your last paragraph is the most correct one. The real benefit of the formal proving process is that it forces the reviewer to actually go through the code. There is no way to just gloss over the code.
I keep hearing that micro-kernals are the way to go, but nobody ever seems to be able to get one finished enough to actually try.
Look at Gnu Hurd, which was started long before the original Linux 0.01 was begun. It has apparentry still not produced a kernal usable enough to build a distribution around. Not everyone starts out as a kernal hacker, but without any working examples to play with and learn from, you aren't going to breed any micro-kernal hackers either.
Re-writing Linux to be a micro-kernal is the wrong way to do it. Linux was designed from the ground up as a monolithic kernal, and changing it to a micro-kernal would involve a total re-write to do it properly. You might as well start from scratch, with a clean micro-kernal design. The only thing you would lose is the magic "Linux" name.
If you want to argue the micro-kernal issue, then get one of the existing micro-kernal projects, like Hurd, finished enough to base a small distribution around (i.e. to a Linux 1.0 level). At that point, it should be easy to attract others in expanding its usefulness.
Who would win this election: Andrew Weiner vs Andrew Weiner's weiner.
You think the XBOX 360 is going to put both Sony and Nintendo out of business? What other competitors in the console business are there?
It doesn't mean much now, it's built for the future.
or
tags to break lines.
You can also set it to default in your user preferences.
And since you can't edit posts here, using the preview mode before posting is also a good idea.
If your queue is unbounded (really a linked list), that could be avoided. What is functionally a queue doesn't always have to be a contiguous queue in memory.
"It's tough to be bilingual when you get hit in the head."
I worked on a commercial microkernel OS.
The learning curve was very steep. New developers took at least half a year to be productive. A number of people never became productive and had to be fired.
Linux is really clean and tidy compared to that. Even BSD is clean and tidy compared to that microkernel OS.
Separated components tend to get complex interactions. Sharing data can be very awkward, even if you are co-located.
Perhaps you should read again the text you quoted, and pay special attention to which process is the one that blocks. And congratulations to the moderator that thinks that a combination of condescension and incomprehension is Insightfull.
Why would you have a single server serving multiple filesystems ? One server instance per filesystem makes a lot more sense, since it's a simpler design and can more effectively use multiple processors.
Well, except if you have a multi-processor machine, and 12+ processes are bombarding the poor filesystem server with requests faster than it can initiate them, at which point the queue starts building up. If I remember correctly, the biggest box Linux has been ran in had 1000 processors...
Or if the server process is performing slowly because some other process with higher priority than the server but lower than the process that initiated the requst is robbing CPU cycles, then the initiating process is in effect being blocked by a lower-priority process. Not good.
Monolithic kernel doesn't have these kind of problems, since the process that initiated the system call is also the one that executes it (in kernel context), and keeps its priority througout the syscall.
And I never said that the server would block, but that the originating process would.
Please understand the problem: it's not that the filesystem server would block, it's that a single-treaded filesystem server can be easily overwhelmed - run out of CPU power - in a multiprocessor machine with several threads making heavy filesystem IO. And the same goes for every other kind of single-treaded server, of course.
Forget magic. Any technology distinguishable from divine power is insufficiently advanced.
Wow! You're cool. How did you implement an unbounded queue (a truly unbounded queue that will never *ever* fill up). At some point won't the entire information capacity of the Universe (which is bounded) run out?
Well, since Linux has in-kernel pre-emption these days, it appears they did :).
When did I ever claim either thing ? All I'm saying that an efficient microkernel is no simpler than an efficient monolithic kernel.
When I'm doing reads, request goes in and data or error code comes out. When I'm doing writes, data goes in and confirmation or error code comes out. Filesystem access is two-way.
Unless the data happens to be in cache in an SMP machine, in which case a simple single-threaded server is going to be bombarded by multiple processes running on multiple processors at once, and run up a queue.
And a multi-threaded server is no simpler than a monolithic kernel filesystem driver, and has some specific problems of its own.
Never underestimate the power of incompetence and architechtural purity combined. Just look at Hurd, with its filesystem servers that work by mapping the whole device into memory at once, and consequently are incapable of using a filesystem larger than a few gigabytes in a 32-bit machine. Dunno if they've got that fixed yet...
Forget magic. Any technology distinguishable from divine power is insufficiently advanced.
There are things which cannot be proven : See this article in Scientific American.
What argument for fascism? Perhaps you should go look up the definition for "fascism". The parent was talking about a benevolent dictator, which is entirely different. Fascism is where corporations control the government.
Everyone already knows a benevolent dictatorship is the best form of government. The problem is finding truly benevolent dictators who have the correct leadership qualities, aren't selfish, really know what's best for their people, and don't get corrupted. The other problem with benevolent dictatorships is finding a replacement for the dictator when he dies who isn't a tyrant.
This macro/micro kernel debate is starting to remind me of an old African proverb:
Two birds disputed about a kernel, when a third swooped down and carried it off.
While the debate is interesting, I rather wish someone would just implement either one, a combination of the two or some other idea that is new.
Say bad words about my book, in cold oatmeal, or I shall sue!
First off I agree with Linus, sort of. I think a hybred would be best. Take a lot of stuff out of the kernel if you can and put it inside it's own addres space. But "balance" and "compromise" is key here the answer is not black or white.
Now to adress the above quote. A DBMS is exactly like a very complex file system. It has many clients reading and writing all at once and performance matters a lot. DBMSes typically run as processes and work well. You can do it by using the process per client method and "pre forking" some server process like Apache does so there is no start up delay. A file system would be a good thing to pull out of the kernel.
I need to look at how Sun implemented ZFS. It is a 128-bit file system that includes the functionality of a volume manager and a RAID system all in one level. Theyu claim it is very fast beating even UFS while adding many, many functions
I would put only hardware device abstraction and process managment inside a kernel but leave where exactly to draw the line up in the air. For example: RAID if you areusing a hardware RAID controller then clearly RAID can't go in userland but what if a user wants to concatinate a SCSI and SATA drive into one logical volume? That can't go into the driver? OK not black and white.
Just to chime in here, I agree - and for those that don't see it: If the program can be proven to be correct via the specification (as input to a program), why not write a parser that takes the specification and generates the code (worst case, have a module that generates random code until the test passes)? If you did that, would we then be in the happy land of no bugs?
What this is: we wrote two programs, and called one a specification. The two programs seem to do the same thing, so we think it is right.
while (sig==sig) sig=!sig;
NFS.
/mnt/]$ mount compy2:/share /mnt/compy2 /mnt/compy2]$ ls -la
1) [root@compy1
2) Unplug cable (power or network) to COMPY2
3) [root@compy1
It will be done right when Duke Nukem: Forever finishes installing.
When modding "Informative", please make sure it both has a source and IS actually informative.
Oh, I agree that the smaller the blocks the easier it is to 'automagically' prove the code. I'll also agree that 20+ years of dev experience have taught me that small blocks are better even if we do not formally prove anything. Small blocks are more likely to be 'visually verified' by the developer and the follow-on developers, reducing bugs. If you can't hold the whole thing in your head, it is more likely to have issues. Compartmentalization is GOOD.
... If you can get a 30% reduction in errors per 1000 lines via a method but you need 2 times the lines you net MORE errors. Assume a statistical 10 errors per 1000 lines and a project of 10,000 lines, that's a likely 100 errors. Now the improved methodology statistically has only 7 errors per 1000 lines (30% better) but the project requires 20,000 lines yielding 140 errors. Now 10,000 of those lines MIGHT be provably correct due to structure, but if you DON'T prove them you have to count them (I agree if you truly prove them you can remove them from the estimate, yielding 70 likely errors).
But more code is more code, if you do not 'prove' the implementation. If compartmentalization reduces the errors per 1000 lines of code from X to Y, say 40% of the original value, you still can not claim a 60% reduction in bugs as the lines of code numbers are different in the different implementations.
To pull numbers out of the air
As I said: In the real world people aren't proving the code, they are claiming it COULD be proven. BZZZZT, thanks for playing. You now have to count the extra code at the lower statistical error rate AND you have to pay the performance penalty. Sometimes the lower rate and the additional code does NOT yield a lower predicted error count so why do it. Sometimes it does yield a lower predicted error count, at a performance hit, yielding a real world trade-off.
ALSO the compartmentalization frequently yields a 'lower exposure' per bug. In a mono kernel exposure is likely all of ring 0. In a microkernel an exposure is not always ring 0, sometimes ring 1 or 2, yielding a POTENTIALLY lower damage/risk. Whether it is ACTUALLY a lower risk depends on how the box/OS is used.
Basically, the whole threat model changes. This leaves you with an apples and pears comparison, not apples to apples. The trade-off needs to understood and an intelligent decision needs to be made. Consequently stating that a general purpose computing platform delivered with a microkernel that has lower performance is better than a monolithic kernel that has better performance is a useless statement (apples to pears).
If you understand the trade-off and the application environment you are applying it to, you can decide if you prefer the shiny apple or the shiny pear. It is NOT a choice between the shiny apple and the wormy apple.
If you want a shiny apple vs. a wormy apple, give me a microkernel environment with better performance than the mono kernel that has less lines of code and a lower statistical error count than the mono kernel and I'll be happy to make the obvious/easy choice.
What I find most interesting about Linus' statement is when you look at Microsoft's Singularity project it twists the statement in knots:
(1) it is about sharing memory spaces
-- like a monolithic design, Singularity shares memory space
(2) it is about the callee changing the caller's state as if it was
his own
-- singlularity uses a variety of mechanisms (primarily
compiler and shared memory messaging primatives) to prevent this.
Singularity is quite revolutionary in that it attempts to adhere to the true microkernel principle (2) while discarding the traditional way of acheiving that principle (1).
Damn, I hate the academic world for letting Microsoft create and patent Singularity! Why didn't MIT, CMU or Berkeley do this research first and put the results in the public domain!
Congratulations! Someone actually got the joke!
.. *my* SparcStation 5 is running Linux
Sorry Andy, thank you for playing!
Comment removed based on user account deletion
Here is the whole article for those who don't have a sciam subscription. Thanks for the pointer to the sciam link,though!
Not a hell of a lot about modern microkernels..
Now, ask him about a traditional old-fashioned monolithic kernel, he knows quite a lot.
---- Booth was a patriot ----
What's the deal with poeple using the word "kernal" instead of "kernel"? Seriously, I find it really difficult to read through some comment or take people seriously when they use this word.
Now consider a microkernel. The filesystem driver is a separate server process. Executing a system call means sending a message to that server and waiting for an answer. Now, what happens if the server is already executing another call ? The calling process blocks, possibly for a long time if there's lots of other requests queued up.
Do magic fairies make the request just happen concurrently without any queueing on monolithic kernels?
Arguing that the calling process always blocks shows a complete lack of understanding of nonblocking I/O. You know, the kind that VMS was built on, and NT uses to good effect (it's about the one design decision it got dead-on right).
> why not write a parser that takes the specification and generates the code
Those are called compilers.
Problem is, people write bad specs. And thus we get bugs.
Done with slashdot, done with nerds, getting a life.
If you really need to test if ((a = malloc(size)) != 0), then leaving in the != 0 suppresses the warning.
How exactly can a post just containing the subject line "comments I liked" and a quote from the linked article be modded up as "insightful"? I mean, it's not like the poster actually added any actual insight beyond him stating that he liked that particular comment. Just curious.
You have no way of knowing what exactly G-d wants you to do. It takes an incredibly conceited man to believe that he he understands all of G-d's motives - a human mind could not even understand a fraction of them. You? you just take your own motives and pretend that they're G-d's.
That is only done to prevent having the application handle the read errors. You can turn off that option if you want...
LedgerSMB: Open source Accounting/ERP
why not write a parser that takes the specification and generates the code (worst case, have a module that generates random code until the test passes)?
Based only on a specification of the human auditory system and information theory, how would you expect a compiler to come up with MP3 or Ogg Vorbis or AAC or whatever?
What this is: we wrote two programs, and called one a specification.
The "spec" proves that a given end result exists. The "program" proves that it is computable. For instance, a "spec" may state that an array is sorted after the method Arrays.sort is called on it. A "program" describes the steps that the hardware takes to produce the end result, such as quicksort (partition through a pivot and sort each side), mergesort (partition halfway, sort each side, and merge the two sides), and heapsort (convert to a priority queue and repeatedly pop the smallest element). Proving this "program" correct involves proving that the means in the "program" produce the result in the "spec".
Of course, the "spec" may itself be a "program" that describes the means to achieve a higher level "spec". Then what you have is a hierarchy of programs and specifications, and at the top is a "spec" of one page that the client has signed off on.
It ought to be obvious to anyone with an ability to look carefully at the industry that these approaches have different problems. High quality and well maintained operating systems have existed for decades that use either approach. The fact that the industry hasn't moved quickly to one or the other can only mean that there is a legitimate tradeoff.
High quality microkernel OS's have included Amiga OS and Unicos/mk (which poweres Crays). I am sure we can all name well engineered monolithic kernel OS's...
I suspect that in massively parallel fast interconnect environments (like a Cray), or in environments where there are certain parallelisms in the hardware (as we saw in the Amiga), microkernel systems probably have an edge. In these environments, you are essentially doing high performance distributed computing anyway, so why not structure your kernel appropriately?
However, note that in these cases concurrency issues are not huge problems. Supercomputers were designed to do one computationally intense task as rapidly as possible, while in a server environment, you may have many simple tasks concurrently. This means either little shared information or a very large number of context switches. In essence, in the standard server environment, the complexity of the status information is likely to be more complex and more free-form. In these cases, it probably makes sense to manage it all in one address space.
Note too that certain architectures, such as the DEC Alpha only have two rings, meaning that your drivers are either fully usermode or fully kernel mode and there is no middle ground. In these architectures, microkernels probably make no sense at all.
LedgerSMB: Open source Accounting/ERP
Damn, I hate the academic world for letting Microsoft create and patent Singularity! Why didn't MIT, CMU or Berkeley do this research first and put the results in the public domain!
_ Systems)) is a great example of prior art, if that is what you are worried about.
While it was a commercial product, Burroughs' Master Control Program (see http://en.wikipedia.org/wiki/MCP_(Burroughs_Large
It is impossible to decide whether a given Turing machine halts in the general case. However, results for Turing machines are not always interesting because physical computing machines are not Turing machines. Notably, physical computing machines lack unbounded memory. A better model for a computer is a linear bounded automaton. All LBAs can be converted into machines that always halt by running them in a virtual machine and looking for cycles in their states.
"Besides, as Linus pointed out, when data is going one way microkernels are easy. And in the case of file systems that is really the case. Sure multiple processes can access it at once, but the time scale on handling the incoming signals is extremely fast compared to waiting for data from disk."
You're forgetting what happens on SMP and multicore systems: multiple processes will be accessing the filesystem at exactly the same time. And the filesystem in its turn will be accessing the block devices, and there will be multiple filesystems on each block device. Plus, the block device will be accesses by the pager/swap.
--- Hindsight is 20/20, but walking backwards is not the answer.
You choose for that filesystem call to wait forever.
/mnt/compy2
/mnt/compy2
Try
mount -o soft compy2:/share
or
mount -o intr compy2:/share
instead
man 8 mount
--- Hindsight is 20/20, but walking backwards is not the answer.
Soooo, something are usefull if they are at least correct and the program should be designed well to do what you want it to do. I agree it's becomes particulary handy when a program can respond to a meltdown effectively. But when it's not proven correct, then you also don't have any guarantee it will function reliable, which is also a kind of usefulness criteria for a nuclear reactor.
Programs which take care of very critical tasks let us say, firing a nuke, should:
1 should be described and clearly with painstaking detail
2 have a wise and smart president
3 have a nonambigeous usable user-interface (especially if 2 happens to be false. maybe a geographic quiz will do)
4 be proven mathematically correct
Wouldn't that be useful?
Sorry, that's too strong. Or misleading. It's no longer the first pass. We're well onto to our 10th or 100th pass, with kernels and operating systems. We're not trying to build the first one. We're trying to build a better one. That means analyze the old to build the new.
That would be like saying the folks coding weather prediction or climate models should code it first in javascript or ruby and then "Optimize" it into FORTRAN "Once the bugs are out". You can't really build a monolithic OS and then optimize it into microkernel. That's a pretty big refactoring!
I18N == Intergalacticization
That was sarcasm.
Don't thank God, thank a doctor!
I don't really give a fork.
The "hard to code" argument is partially valid, but I think the developers are not "stupid" and could cope with it. Linus goes a long way to show that microkernel are not easier to _develop_ -- I don't think that was ever the case though. Micro- doesn't mean simple.
The spec is just a description of desired properties of the program. For example:
- "The program never accesses unallocated memory"
- "The function always returns"
- "The result of the function foo has has relation bar wrt. the input"
- "These processes never end up in deadlock"
- "Resource starvation will never occur"
- "The program will never crash"
and so forth. Automatically proving such properties for your program is not comparable to "trying it for a lot of different input, really". Especially for concurrent programs, many bugs are really difficult to reproduce and only occur under special circumstances. If you can prove that your program is "correct" in one of the above senses *for all possible input*, i.e. *no matter what*, then you have done something entirely different (and a *lot* more) than testing it.
Did I remember all your crackpot theories? I recognized them instantly, and your website linked in your sig confirmed it was the same bullshit again.
"the ability to prove (even mathematically) that the kernel is correct. " "That is why critical real-time OSes are often based on a microkernel which is only about 4000-8000 lines of code. Even at that size is might take years to prove it does what it is supposed to do."
That doesn't help you. What you're saying is: strip off all drivers from the kernel, so you can prove the kernel is correct.
So what if a filesystem driver corrupts the data when the microkernel schedules it in a certain way compared to the block device driver and the swap/pager? You still have to prove all the driver, and you still have the same complicated real-life the driverkernel interactions as without a microkernel.
"critical real-time OSes" make things more reliable by not allowing the system to do many complex (and therefore potentially dangerous) things in parallel. Single tasks running in sequence, programmed to execute with guaranteed run-times can be extremely predictable (thus reliable). That can reduce the number of fault cases, but it's not guaranteed that allowing the complexs situations to occur adds fault cases (that is a likely possibility, but not a guarantee), but what is guaranteed is that the microkernel approach takes away performance.
--- Hindsight is 20/20, but walking backwards is not the answer.
This is lame. It's dishonest to put words in somebody's mouth that they did not speak or make claims on their behalf. May your karma catch up with you. ahahaha...
And traditional monolithic kernels are buggy, and unreliable. This too has been proven time and time again. The important question is: what's more important to you, development speed, or reliability?
It's a balance between the two, and in real life the fact that people were choosing Windows 98 over more stable alternatives shows that features (achieved through faster development) are generally preferred over absolute stability.
But in real life, monolithic kernels tend to be more reliable than microkernel systems with equivalent features anyway, so it's not really a question of making that tradeoff by choosing microkernel vs. monolithic kernel; the fact that you can develop faster also means you can fix bugs faster.
The only reason people have a perception of microkernels being more stable is because microkernels are so hard to develop that they tend to stagnate feature-wise, and all stagnant systems that are still maintained tend toward bug-fixing and stability.
Hence all major consumer OSes are monolithic. Some start off with a microkernel approach, but they all move to a monolithic approach (see: MacOS X, Windows NT/XP).
Even most complex embedded systems are monolithic; they'll claim that there's a microkernel, but often that's basically a lie and there's a micro-supervisor that takes care of scheduling 2 monolithic kernels (one for "critical" stuff and the other for bells and whistles), which is really not very different from, say, RTLinux.
Now, for simple systems microkernel systems are often an excellent choice. But I haven't seen a single one that competes on a per-feature basis with major monolithic kernels successfully without essentially scheduling a monolithic kernel to support all the interesting stuff; QNX is probably the closest, but it's a pretty far cry from a modern Linux, BSD, XP, or MacOS X system feature-wise.
rage, rage against the dying of the light
"Here, it seems, the means justify the ends. Linus basically says "I won't take any challenges"."
Nope, he is making some pretty bold statements that tell the microkernel people 'go ahead, build it and show me wrong'.
--- Hindsight is 20/20, but walking backwards is not the answer.
"The problem is that the formal specification is just as or even more complicated to read and write than the implementation itself." Certainly not all is roses with formal verification. Few people have the mathematical background, experience, desire, time, etc. to make much use of formal verification, and even experts have to do a lot of work to prove anything interesting about real programs, and expertise + time is costly. But, I don't agree that specifications are, on the average, as complicated as their implementations. For example, imagine a system for implementing a potentially very large but sparse array. It might be quite complex in order to be efficient. But its interface might be quite simple (i.e., "load" and "store"), and correctness properties might be very succinctly stated, e.g., load(addr1,store(addr1,val,mem)) = val, addr1 != addr2 -> load(addr1,store(addr2,val,mem)) = load(addr1,mem) store(addr1,load(addr1,mem),mem) = mem store(addr1,val1,store(addr1,val2,mem)) = store(addr1,val1,mem) addr1 != addr2 -> store(addr1,val1,store(addr2,val2,mem)) = store(addr2,val2,store(addr1,val1,mem)) In cases where properties like these are not easy to state or prove, it may still be possible to show that some convoluted but efficient program behaves the same as another program which is very simple but would be too inefficient to use. These sorts of proofs add a lot of value, because you can now just consider the correctness of the simple but inefficient program.
To me, it comes down to the fact that if you want to build really robust systems, guess what, you have to deal with that "decentralized" problem. It doesn't go away. A local display is a lot simpler to create. A distributed display, like X11, is a lot more complicated, but opens a new world of possibilities. Same goes for everything else: distributed disk, distributed compute resources, distributed input devices (multiple keyboards, mice, anyone?), distributed screens, distributed media production/consumption (phonon, nimm: http://www.linuxdevices.com/news/NS5209121793.html ).
So eventually you have to solve the problem. Might as well drive the solution straight to the core of the kernel so it can handle these situations natively.
It's 10 PM. Do you know if you're un-American?
"If a 32-bit address falls within the current segment, then the instruction is executed, otherwise a new segment is loaded from the address and a security check is performed."
checking "falls within" for each memory access? That is not a simple operation in hardware. The data structures for the segments are also likely to be pretty large.
That would take quite a lot of registers and logic to make that run at 3GHz (cache doesn't run that fast, so all data would have to be in registers). Be prepared to have to accept significantly higher power consumption and prices for processors that do that.
--- Hindsight is 20/20, but walking backwards is not the answer.
You don't need to have separate address spaces for your objects. You can solve this problem with language-based technologies and get better performance too.
See Deconstructing Process IsolationMark Aiken; Manuel Fahndrich; Chris Hawblitzel; Galen Hunt; James R. Larus. April 2006
The paper concludes that hardware-based isolation incurs performance costs of up to 25-33%, while the lower cost of SIPs permits them to provide protection and failure isolation at a finer granularity than conventional processes.
But in real life, monolithic kernels tend to be more reliable than microkernel systems with equivalent features anyway, so it's not really a question of making that tradeoff by choosing microkernel vs. monolithic kernel; the fact that you can develop faster also means you can fix bugs faster.
I think you should review your history. In particular, investigate KeyKOS back in the early 80s, a microkernel-based operating system which operated for decades, and which hosted a fully binary-compatible UNIX environment. I would say that qualifies for a system of "equivalent features", and KeyKOS was much safer, much more reliable, and far more secure than any monolithic system you'll find in existence then or now.
The reason monolithic kernels are more prevalent is that the kernel development model is so much simpler, that even hobbiest and newbie programmers can experiment with it (and it sometimes shows in open source kernels). Microkernel development (the actual kernel) is simply harder because appropriate tradeoffs demand much more architectural and hardware knowledge from the developer.
I don't see how the userland development need be any more complicated for microkernels than monolithic. Plenty of microkernels, both old and new, have provided unix environments; granted, some of those were no safer than their unix counterparts, but that is a matter of proper design and not an inherent limitation of the core microkernel architecture (see KeyKOS, Xen, L4).
QNX is probably the closest, but it's a pretty far cry from a modern Linux, BSD, XP, or MacOS X system feature-wise.
Only because it's not targeted for the same market. Their preview desktop release a few years ago was still quite impressive.
Higher Logics: where programming meets science.
;) Fair point, but in a monolithic kernel all the library routines share the same address space and run in supervisor mode. I'm talking about userspace libraries that would have access to the address space of the calling process but not vice versa. Maybe the similarity to a monolithic kernel would make it easier to convert existing kernel modules into libraries?
your halting detector will indeed halt, but not in the lifetime of this universe for most programs
It was an upper bound.
A lot of people who post to Slashdot and elsewhere are unfamiliar with the definition of a Turing machine or its implications, especially the difference between Turing machines and the machine in front of them. They like to discount the possibility of correctness proofs on the basis that just because "the halting problem on a Turing machine is undecidable" that the halting problem on a real computer must be undecidable. In fact, there exists a worst-case decider for all real computers that reduces the impossible to intractable. From there, a bit more research may result in a practical program prover that can reject most of those 2^(2^40) potential states.
An example of a problem for a program prover:
Arguably it's not really relevant either. "proving" a software program only proves that the programs conforms to the spec. Now who proves the spec? And who proves the proof?
Mod parent up.
You're friggin' correct. Going even further, you would have to prove the correct functioning of a circuit at the individual transistor level. An what if a cosmic ray hits?
Sure, proofs may help to investigate code more thoroughly. But so do unit tests and other measures.
I think the whole 'proof your code' issue comes from those computer scientists which take the way math -> CS and not physics -> CS. No question, the former group of people is important for theoretic computer science. But some of them forget that a computer is a real, physical device. And most of the pen-and-paper mathematical work in CS someday lands on real physical devices.
modern desktop computer
Modern desktop computers are a mature industry running on razor-thin margins. The next big profit center is handheld devices of some sort. Is it straightforward to get Windows to cross-compile a Linux kernel for a handheld device?
Specifications are often simpler than programs.
Write a network driver sometime, the program is simple, the spec is horrendous (lists of registers and 'expected behaviour' of the hardware) the proof, almost impossible (vast numbers of settings and conditions).
Specs for things inside an operating system are usually much easier to test, all the interfaces go to known code, in the case of hardware and the wild world outside of the computer, who knows.
Ah, you mean to prove that the microkernel is correct. Which is all fine and dandy. But pretty useless, considering that about the only thing of any value a microkernel does, is managing processes, memory and IPC. Without a gazillion other drivers/processes/whatever, your microkernel is useless, and with a gazillion drivers/processes/whatever (all communicating in a nonobvious distributed manner), your proof is useless.
That is why critical real-time OSes are often based on a microkernel which is only about 4000-8000 lines of code.
Hmm, and here I thought most real-time operating systems were basically a boot-loader, a C library, usually a scheduler, and some way to link the OS with your app. Sure QNX is cool and all, but it's hardly a typical representative of real-time operating systems.
If the same happens in the microkernel system, the kernel will reload the driver, raise an alarm, or in general -- be able to take the system to a predictable predetermined state. Going back to the analogy is it is like having the dictator execute a corrupted staff member and replace him immediately.
If the driver is so flaky that it constantly fails and needs to restart, maybe you should look at the driver for the solution to your problem, instead of building a complicated microkernel just to have a restartable driver. If the driver is stable, then how the fuck are you supposed to know that this restarting magic actually works?
Good thing if the system was only running Doom at the time and not controlling a reactor, or administering a drug.
If it was a hard realtime system (as reactor/drug implies), then you have already lost. Your driver failed, and no matter how flawless the "restarting driver"-magic is, you have already broken you real-time deadline.
Bzzt, wrong! Quicksort is almost a one-liner. In C, you might get 5 or 6 lines, but it's hardly difficult.
Contrast that with saying in a formal way that the output (Y) of qsort is an ordered permutation of the elements given as input (X).
Assume:
Y = quicksort(X),
X element-of int-sequence,
Y element-of int-sequence, and
n = length-of X
then:
n = length-of Y
for-all i element-of 1..n exists j element-of 1..n such-that X_i = Y_j
not (exist j element of 1..n such-that for-all i element-of 1..n X_i =/= Y_j)
for-all j element-of 2..n Y_{j-1} <= Y_j
Note the extremely convoluted way of telling that Y was a permutation of X (I'm not even sure it's sufficient). In contrast, telling that Y is sorted was easy. Now you have to prove it.
Personally, I'm pretty much convinced by this example that informal proofs are the best. Let's prove that Y is sorted, and don't bother about proving that Y is a permutation of X, because that is "obvious" by inspection.
If we accept the premise that even a very narrow definition of God in which (he, she, it) exists, then why would it not well within his ability to provide a way for a person to know what it is God wants that person to do? People themselves are capable in varying degrees of communicating to others what they want in an imprecise manner. For one person to work towards what God wants him to do, it does not require that he know all of God's motives, just the ones that involve that person. It seems to me that I do much more than take my own motives and pretend that they're God's, I take a look at what motives I could take as my own and figure out whether or not they are from God. I also start with the premise that God wants to drive out evil, and then look for what will drive out evil, wherever it lies, in me, in another person, or in something else altogether. Once evil is driven out, what remains is of God.
So why do the makers of real-time OSes spend months to get their products certified for covert channel analysis. How silly of them to do that, they should really just forget it because cosmic rays will come down and burn the transistors anyway, right?
Fundamentally, if you care about scalability, you need locking for managing your resources, regardless of whether you have a microkernel or a monolithic one, because the on-disk data structures are a shared resource.
You need locking if you want to have things run in a multi-threaded way. However, I would argue that it is much easier to design and manage your locking protocols when you (you includes the development team for your server) are the only ones who have to really understand them and use them.
With this, you reduce the chance that code outside of your driver but inside the kernel could write to your driver's address space, which isn't, in practice, a common occurance, because other code generally won't have pointers that go there.
When a pointer can be created from an integer and when you have functions like "strcpy" which will run happily through memory if you don't have a terminating null, you have a lot of chances for other code to overwrite your data structures. What is this "your driver's address space" you speak of? Doesn't exist in a monolithic kernel. You might have pre-allocated a bunch of space for yourself to use, but it all comes out of the common pool(s) and it's all in the same address space.
Obvious problems with R, MySQL "benchmarks"...
I've posted about MySQL's problems before; they could get about a 15% performance improvement on Linux and a huge performance improvement on MacOS X just by pipelining their requests. This would require a library change (2/3s of the improvement) and a change to the way requests are dequeued on the server (about 1/3).
The R problem is 50% him not passing "-O2 -fstrict-aliasing" to the compiler, and 50% him using the system malloc instead of dlmalloc like it says to use in the R admin manual.
I have to agree with the parent poster on this one; I wouldn't have said things quite that way, but then the guy who did the R "benchmark" was pretty inflamatory in his comments, too.
-- Terry
Based on recent research, a microkernel approach will be more suitable for highly distributed and expandable self-aware and self-replicating computer-based lifeforms. As we develop the technology to replace ourselves and create the ultimate race of Berserkers, Linux will be replaced as the O/S of choice by a more partitioned and distributed microkernel based on a future version of L4 merged with Mach.
"The fundamental result of access space separation is that you can't share data structures. That means that you can't share locking, it means that you must copy any shared data, and that in turn means that you have a much harder time handling coherency. All your algorithms basically end up being distributed algorithms. ... on typical modern hardware. I can imagine hardware which would support these tasks to make them fast and easy. Before you guffaw too loudly, remember linux would only run on hardware with a MMU for quite a long time.
I wonder if any of Intel's VT instructions could be tickled for something like this (I don't know enough about it).
My God, it's Full of Source!
OUTSIDE_IP=$(dig +short my.ip @outsideip.net)
This post was up earlier: http://www.computer.org/portal/site/computer/menui tem.5d61c1d591162e4b0ef1bd108bcd45f3/index.jsp?&pN ame=computer_level1_article&TheCat=1005&path=compu ter/homepage/0506&file=cover1.xml&xsl=article.xsl&
and what struck me is how many of these problems go away if the hardware context is encoded in the PTP/PTE for a page of memory. SPARC does this. Contexts could be created for drivers and the driver could address only that set of pages of memory, and not the whole kernel.
WRONG. If the bug is in the interrupt handler, it will freeze any AMD64 or x86 system due to architecture limitations...
Which is why the interupt handler is part of the microkernel. If the microkernel has been proved correct, the interupt handler is bug free.
But 80x86 processors already do the job of checking if memory addresses fall within the current segment; and not one segment only, but one of the CS, DS, SS, ES, GS and FS segments of each process, depending on instruction. These processors also have a segment descriptor table which is read each time there is a kernel call (which is 99% of what a program does anyway, since windows messages are generated from the kernel); and each kernel access goes through a 'double-dispatch' ring protection check mechanism which reads two entries of the segment table: one for the ring, and one for the target segment. So I do not see any big performance hit.
There is also another technique that the Motorola 68020 used (as indicated by another post). It goes like this: each procedure is marked with an entry point which defines the attributes of the current module (base address, limit, access type). Each time a CALL instruction is executed, the CPU pushes the old module description in the stack and loads a new module descriptor from the destination address. Upon return, the module pointer is restored from the stack contents. This can be applied on 80x86 with minimal cost: the entry point of each procedure shall be the id of the segment descriptor of the module. Each time there is a call, the register CS is pushed to the stack, and then is loaded with the value found in the destination address, while at the same time an access check is performed. The call instruction can be special (like MC68020's CALLM), so as that the current code is unaffected; all that is needed is for the O/S linker to patch each exported procedure's entry point with its segment id, and replace the instruction CALL with CALLM for each call to an exported procedure defined in a dll/vxd/so/other module type.
IF these N x 100 drivers are compiled into the plane, they're probably critical to the system, no?
Your proposal of a checked microkernel with unchecked user-space drivers is better how? Your plane will certainly allocate memory and schedule processes correcly, all the way into a mountain.
The microkernel running the same hardware as a monolithic one will be bigger. It's more complex by design. If, on the other hand, all you need is one or five processes calculating speed & altitude, then the microkernel vs. monolithic argument is just insane. You don't run N x 100 drivers and play mp3:s on a plane's computer.
For just a few processes a monolithic approach is probably best. You have less code to look after. At some point you reach a level where you can't trust all your code, but some drivers are not nessesary for the critical operation. That's the spot for a microkernel. When you continue to buld an even more complex system, which is to do alot of things, you suddenly find yourself with so many critical operations that you simply can't manage them all; then you move back to monolithic, because it's less code.
do some asynchronous juggling to be efficient.
Ehhhm. This is exactly the complexity that you're trying to avoid in a microkernel.
You want central services to take the complexity out of the different drivers.
CS/DS/SS/ES are from the 16-bit time. (and btw, they were a bad idea then, so doing something like that again is bad now too). When processors were 16-bit, they had a lot less memory than they have now. Today, those couple of registers are not going to be enough.
Did you notice that for each definable segment, there is a separate register? That is because only registers are fast enough.
Adding stack (memory!) operations to each function call slows down things a lot too.
"while at the same time an access check is performed"
What you're missing is that calls are all over the code, at many different addresses, so to do an 'access check' requires an add an a subtract for each possible active segment. That is a lot of operations.
Seems to me that everything you're talking about is best done completely in software.
--- Hindsight is 20/20, but walking backwards is not the answer.
huh. I really had no idea about that.
:)
Thanks
When modding "Informative", please make sure it both has a source and IS actually informative.
I think you mis-understand. Monolithic is like a central dictatorship. When there is a benevolent dictator it works well, but in case of a bad one you get a mis-managed affair, where everybody is destroying things for everybody else. While Micro-kernel is a Burocracy, where the system is trying to keep everybody from hurting everybody else. This results in lots of inefficiencies. The system is useful because it works with the normal human greed, being compartmentalised. But a benevolent dictator is the most efficient solution, and it does work in the Open Source world. I would recommend Microkernels for Proprietory systems where many companies where going to work on adding features to the micro-kernel. This is exactly where QNX rules.
I thought you were making that word up! You weren't.
Software sucks. Open Source sucks less.
I posted Linus' comment, and I agree, of course. I've sometimes spent 15 minutes writing a comment I thought was useful, and been moderated down to -1.
Now I seem to be getting credit for Torvald's thinking.
Or, maybe I was moderated up for having the brains to re-format what Linus said so that it is more readable?
I think you should review your history. In particular, investigate KeyKOS back in the early 80s, a microkernel-based operating system which operated for decades, and which hosted a fully binary-compatible UNIX environment. I would say that qualifies for a system of "equivalent features"
Great example.
By design it was impossible for KeyKOS to support variable-sized inodes or disk blocks, partition resizing, etc. Even removable media (floppy disks) were a horrible kludge that often threw the object store into an inconsistent state.
Working core dumps (and I'm talking of user applications, not the kernel) were completely impossible under the KeyKOS design, making debugging very difficult (and they tried to spin that as a positive!).
The checkpoint/transaction manager was a performance nightmare once you had to scale to multiple concurrent processes; single process (which were all KeyKOS generally published benchmarks for, aside from a well-known carefully constructed transaction benchmark explicitly designed to make sure that only completely independent data was ever written to the system) were pretty efficient, but tangled references quickly forced the set of objects that needed to be committed to the ENTIRE SYSTEM once you had a fair number of processes running at once. Disk usage was incredibly inefficient.
Moreover, the checkpoint system wasn't ACID compliant so you didn't get anything useful for all that complexity; in crash recovery situations, a transaction that had already been committed could be replayed multiple times (causing data inconsistencies or worse).
I could go on, but the major point is that all of these problems stemmed directly from the design of the KeyKOS microkernel, and the barriers to solutions were ones that would not have existed in a monolithic kernel.
None of those problems were easily soluable, and the attempt to improve the system in EROS wound up in a development rathole that was eventually abandoned because of systemic complexity and severe performance problems. Attempts to follow it up (notably CaprOS with the EROS code, and Coyotos recoding the design from scratch) also have achieved little to date.
rage, rage against the dying of the light
By design it was impossible for KeyKOS to support variable-sized inodes or disk blocks, partition resizing, etc.
KeyKOS had no notion of inodes or diskblocks, it had a single-level store. Files and filesystems were implemented by processes that operated on red-black trees. There is nothing in the design the precludes the features you mention. Unless of course, you are discussing how to manage storage add/remove disks, etc. when using a single-level store. This is a completely separate issue from microkernels and the KeyKOS architecture.
Even removable media (floppy disks) were a horrible kludge that often threw the object store into an inconsistent state.
Once again removable media are sometimes a problem for single-level stores, not for microkernels or KeyKOS/EROS in particular. I also highly doubt your claim of inconsistency, as the developers were very careful to avoid those ends, so please provide a pointer to validate this claim.
The checkpoint/transaction manager was a performance nightmare once you had to scale to multiple concurrent processes; single process (which were all KeyKOS generally published benchmarks for, aside from a well-known carefully constructed transaction benchmark explicitly designed to make sure that only completely independent data was ever written to the system) were pretty efficient, but tangled references quickly forced the set of objects that needed to be committed to the ENTIRE SYSTEM once you had a fair number of processes running at once. Disk usage was incredibly inefficient.
This paragraph leads me to believe that you have little idea about how KeyKOS operated. KeyKOS and its successors are built on transparent orthogonal persistence, which means a snapshot of the entire system is always written to disk as an atomic transaction. Contrary to your assertion, disk usage has been shown to be incredibly efficient.
Unless by "transaction manager" you're talking about the ATM software which ran on KeyKOS, which would be a completely different matter and unrelated to KeyKOS as a viable OS.
Moreover, the checkpoint system wasn't ACID compliant so you didn't get anything useful for all that complexity; in crash recovery situations, a transaction that had already been committed could be replayed multiple times (causing data inconsistencies or worse).
Checkpointing is and was ACID. If you believe it was not, then please explain.
I could go on, but the major point is that all of these problems stemmed directly from the design of the KeyKOS microkernel, and the barriers to solutions were ones that would not have existed in a monolithic kernel.
Completely untrue. I suggest you read some KeyKOS kernel and architecture papers to learn the true limits of KeyKOS.
None of those problems were easily soluable, and the attempt to improve the system in EROS wound up in a development rathole that was eventually abandoned because of systemic complexity and severe performance problems.
Only partly true. The EROS founder abandoned it in favour of Coyotos because the reliability guarantees achievable via C-based development were too low, and the message passing primitives which defined the architecture made "certain" high-performance designs challenging. This is not "severe" performance problems, any more than Linux had "severe" performance problems before epoll. By high-performance, we're talking saturating Gigabit ethernet here (EROS achieved 90% saturation), which is above and beyond the bandwidth needed for most uses.
Attempts to follow it up (notably CaprOS with the EROS code, and Coyotos recoding the design from scratch) also have achieved little to date.
It's been a year. CapROS has been ported to the ARM, the Coyotos group has developed the BitC language, and the
Higher Logics: where programming meets science.
We don't attack Windows running GDI in kernel. Actually, it was a good move, which showed exactly why microkernel didn't work in real life as a general purpose OS.
We attack because Microsoft is not honest about it and still talks about "microkernel" while they know it's not.
I have to laugh when you say NT is more modular.
Look at which system has the biggest number of supported filesystems, and then talk about modularity.
Linux VFS is a great example of modularity design. Actually, the credit goes back to Sun's Solaris when they introduced NFS.
Please, know what you are talking about instead of just buying everything MS marketing has to say.
QNX
Possilibity, Dogma, etc, are not truth. You take them to be, and that is incorrect and intellectually lazy.
You know, I've seen EMI-certified screws.
Now consider a microkernel. The filesystem driver is a separate server process. Executing a system call means sending a message to that server and waiting for an answer. Now, what happens if the server is already executing another call ?
The same thing as you suggest when it happens in a monolithic kernel, The multi threaded fs server uses appropriate locking and preemption to make sure the request can be fulfilled as quickly as possible. That would be the proper locking and preemption needed for an OS service. Nobody claimed that microkernel was a magic free pass that lets you get away with crappy implementations.
The other issues with deadlocking are solved with proper priority inheritance. If a high priority process is blocking on the fs server, then the fs server is promoted to it's priority. In many microkernel systems, making a blocking IPC call also yields the remainder of the calling process' timeslice to the called process. Given a good threaded server daemon design, much of the complexity of getting locking and preemption right 'just works'. At the very least, it's no more complex than getting it right in a monokernel.
Things in the Linux monokernel work exactly the same way! The kernel code inherits the timeslice of the process that makes the system call. Unlike an fs server, if the Linux fs code makes a mistake, it can lock up the entire system until reset.
It has been a long time since the Linux kernel was single threaded. Think the 'big kernel lock' and the considerable effort that went into getting rid of it. The linux kernel's threading is mostly cooperative with the exception of interrupt handlers.
Sure, there are ways around this. The server could be multi-threaded, for example. But how many threads should it spawn ? And how much system resources are they going to waste ? A monolithic kernel has none of these problems.
If those threads are blocking on a work queue, the 'wasted' system resources amounts to a few process table entries (a few KB)
"CS/DS/SS/ES are from the 16-bit time. (and btw, they were a bad idea then, so doing something like that again is bad now too)"
Segmentation as it was introduced on 80x86 is a bad idea indeed. What I proposed was a way to exploit segmentation in order to have modularization.
"Did you notice that for each definable segment, there is a separate register? That is because only registers are fast enough."
Not really. Registers are caches for segment indices. The segment information is stored either the global descriptor or local descriptor table.
"Adding stack (memory!) operations to each function call slows down things a lot too."
No, it will not. We are talking 32 bits more per call. That's negligible, since the stack areas will already be in cache anyway.
"What you're missing is that calls are all over the code, at many different addresses, so to do an 'access check' requires an add an a subtract for each possible active segment. That is a lot of operations."
And what you don't understand is that these checks are already performed at each call. And not only there is a segment limit check, but since most calls will call the kernel, there is also a jump from higher to lower ring as well (and that is costly!).
"Seems to me that everything you're talking about is best done completely in software."
It seems to me you have no idea how 80x86 works.
Throughout this discussion, one common theme is mis-understanding a few concepts by taking them as explicit and literal.
For an eaxmple, passing a 'message'. Many hear this and think it's necessarily writing some structure to a socket like object. In fact, any system call can be seen as passing a message. It might be a write to a socket, or it could be (on intel platforms) the assembly instruction int $0x80. in fact, writing to a socket would be passing a message through a syscall in order to request that a message be passed through a socket.
Shared memory is another example. At the program level, it looks different than message passing, but that's only because SMP capable processors have considerable amounts of hardware dedicated to converting those 'simple' memory accesses into explicit messages from CPU to CPU (to maintain cache coherency) as well as CPU to memory controller (an internal message in an Opteron) and memory controller to RAM. RAM is a simple (or these days NOT so simple) state machine that recieves read and write messages from a memory controller and sends back acknowledgements and data. The fact that it's all swept under the rug by the CPU doesn't mean it never happened, just that the programmer doesn't have to code it.
However, a progremmer using shared memory DOES have to at least be aware of it if the code is to be efficient. For example, if you know the size of a cache line and how the data will be accessed, you are well advised to arrange the data such that only one thread will be modifying data on a single cache line at the same time, and so where possible, data that is accessed as a unit resides in the same cache line (that is, good data locality).
Shared memory to message passing CAN be implemented in software. I have done it as an experiment using a signal handler to catch SEGV and explicitly fault the page over to the process trying to write by passing messages to other processes 'sharing' the memory. That can be horribly slow, especially if you use TCP/IP to pass the messages, but when handled by dedicated hardware (such as the CPUs on a multiprocessor machine) can be fast enough that many forget that it happens at all.
A function call is a sort of message passing. In this case, the compiler hides the complexity. Try gcc -s on your favorite hello world program in C and you'll see where the compiler has arranged to push the relevant variables onto the stack, that is it builds a message. Then it executes a call instruction (passes the message). In this case, the stack frame and instruction pointer are the context that gets switched.
In that sense, the difference between micro and mono kernel is how the message passing is implemented and how explicitly. The performance differences are a matter of how well the hardware supports the message passing scheme.
It is noteworthy that when Linus was discussing mono vs. micro the first time, the hardware that concerned him supported monokernel style message passing MUCH better than any of the methods in use by microkernels. That appears to still be true.
So, it comes down to the tradeoffs between speed, stability, verasatility, and development and maintainance. One noteworthy benefit to development is that it's easier to test (for example) a new fs server by giving it an example filesystem to support for the developer. It can then be run in a debugger if necessary and if it crashes and burns, the rest of the system is just fine (including the old FS service).
back in the '386 days, speed was a real issue in most cases. These days, a great many systems have 'speed to burn'. So for the same reason most generally agree that there's no good reason to use every possible dirty assembler trick for a web server (in fact, many good reasons NOT to), it may be time to ask if the benefits outweigh the performance costs in a microkernel approach.
Also worth noting, it's not as if the Linux kernel needs to be abandoned and replaced. For example, fuse IS a filesystem running as a userspace service. It's probably not going to be deployed as the root filesystem anytime soon, but it exists. There's also 9fs.
HURD is the true GNU microkernel based on mach.
www.gnu.org/software/hurd/hurd.html
> "Did you notice that for each definable segment, there is a separate register? That is because only registers are fast enough."
>> "Not really. Registers are caches for segment indices. The segment information is stored either the global descriptor or local descriptor table."
Nope. CS/DS/SS/ES are not caches they are actual registers. Registers are never caches, registers are (simple) flip-flops. Caches are (mostly) SRAM. Totally different beasts.
"No, it will not. We are talking 32 bits more per call. That's negligible,"
It's not.
"That's negligible, since the stack areas will already be in cache anyway."
Besides adding cycles to basic instructions such as a call, you're adding significantly to the memory bandwidth.
"And what you don't understand is that these checks are already performed at each call. And not only there is a segment limit check, but since most calls will call the kernel, there is also a jump from higher to lower ring as well (and that is costly!)."
Nope, 'the checks' are a result of being able to know 'page faults', and each page is 4kbyte (or more for hugetlb), and if page boundaries are not crossed, no checks are needed so none are done. They actually added hugetlb support to the chips to not only reduce the table sizes, but also to reduce the number of page boundary crossings, to improve the performance.
"It seems to me you have no idea how 80x86 works."
Seems to me that you are a software person who thinks he knows hardware.
--- Hindsight is 20/20, but walking backwards is not the answer.
Oh I think making an efficient microkernel is harder than a macrokernel. The reason for doing it are typically in spite of performance issues.
But your post blew up the problems of a microkernel while completely dismissing the hardships of a macrokernel. My point was that both have problematic areas.
Both micro- and macrokernels are going to have issues with actual reading from disk. The problem being that you can only read from one place at a time (not strictly true, but there are limits). As such multiple processes which attempt to read at the same time need to be handled by some sort of queueing system. It's just a question of where you put that.
Besides my point was that it doesn't matter if you application is the only one running on a macrokernel OS. Disk access takes a long time, so you *will* be blocked for some time. (Or you'll have to implement asyncronous file access.)
Yes, but for each operation the data is only going one way. And that's the point.
Microkernels are slow if you have to send a lot of data back and forth rapidly. (And in this context anything leaving RAM is slow.)