13 ms·
> Microkernels don't need memory management. Of course they do. It takes memory to hold metadata about a process. It takes memory to hold resources about other
by kllrnohj 9y ago
> Microkernels don't need memory management.
Of course they do. It takes memory to hold metadata about a process. It takes memory to hold resources about other services. It takes memory to pass data between them.
Just because that memory is reserved at boot doesn't mean it suddenly has no lifecycle of any kind.
> Furthermore, you don't want exceptions in kernel code.
Nobody said anything about C++ throw/catch exceptions.
> Simply put, there is no reason to choose C++ for a microkernel, and many, many reasons not to.
If you want to avoid C++ that's great, but to argue for C over it is insanity rooted in nostalgia.
- naasking 9y ago> Just because that memory is reserved at boot doesn't mean it suddenly has no lifecycle of any kind. Yes it does. The "lifecycle" is: allocate at boot, machine halts. All of the memory you describe for other purposes is allocated at user level and booked to processes. This is how you make a kernel immune to DoS. > Nobody said anything about C++ throw/catch exceptions. That's the only meaningful difference in error handling between C and C++. Since you mentioned error handling as a reason to choose C++, what else could you possibly mean? > If you want to avoid C++ that's great, but to argue for C over it is insanity rooted in nostalgia. Sure, you keep believing that. It's clear you're not familiar with microkernel design. The advantages C++ has for application-level programming are useless in this domain.
- mortdeus 9y agohow about we argue the impossibility of most people ever being able to understand what's going on in C++ code (even their own code) and the cataclysmic consequences of using an over convoluted language? I mean there is a reason why the original pioneers of C don't use C++. (i mean other than the fact that dmr is dead)
- paulhilbert 9y agoSo goto spaghetti is understandable? And dropping those isn't an argument since proper C++ usage also implies agreeing on a proper subset of the language to use. Modern C++ with sane restrictions is way more easy to understand. Especially w.r.t. resource ownership and lifetimes (as pointed out).
- laumars 9y agoI'm not going to argue that one language is better than another but I do honestly get sick of all this "goto" bashing that often rears it's head. Like all programming constructs, goto can be ugly when it is misused. But there's times when I've simplified code and made it far more readable by stripping out multiple lines of structured code and replacing it with a single goto. So if you're going to argue in favour of C++ with the caveat of good developer practices then you must also make the same caveat of C (ie you cannot play the "goto spaghetti" card) otherwise you're just intentially skewing your comparison to win a pointless internet argument.
- paulhilbert 9y agoNo, I would never argue for C++. The reason being mostly its toolsets (constantly changing, instable and often incoherent). I just don't think readability is an argument - and I am as sick of (pointless) arguments against C++'s readability as you are about goto arguments :) Edit: Just to be clear - there are actual arguments against C's readability. For example when figuring out where and when data gets deleted - but as others have pointed out dynamic memory management is a whole different beast in kernel wonderland.
- coldtea 9y ago>So goto spaghetti is understandable? There's no goto spaghetti in C -- it's only used for local error handling, not for jumping around, at least since the 70s...
- pjmlp 9y ago> I mean there is a reason why the original pioneers of C don't use C++. (i mean other than the fact that dmr is dead) Bjarne created C++ exactly because he didn't want to repeat the experience he had, when he lost his Simula productivity to BCPL. Of course the C designers thought otherwise of their own baby.
- 72deluxe 9y agoI understand my code - the language doesn't dictate the understandability of the code that is written. Any language can be used to write indecipherable bad code. You are blaming the wrong thing. C++ seems to be very widely used to write some amazing things, despite your apparent hatred of it?
- fauigerzigerk 9y agoWould you really say that this sort of complexity is just down to writing indecipherable bad code? https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers https://isocpp.org/blog/2012/11/universal-references-in-c11-... In my view C++ is a very complex language that only few people can write safely and productively. When you say "I understand my code" I have to believe you. The problem is that understanding other people's C++ code takes ages, even if they don't abuse the language. Trusting their code is another story entirely. C++ is a very flexible language in that it puts few restrictions on redefining the meaning of any particular syntactic expression. That's great, but it also means that there is a lot of non-local information that you have to be aware of in order to understand what any particular piece of code actually does. I'm not surprised that C++ is both loved and hated and perhaps even more often simply accepted as the only practical choice. There aren't many widely used languages around that allow us to optimize our code almost without limit and at the same time provide powerful abstraction facilities. At the same time, there aren't many widely used languages around that make reading other people's code as difficult as C++ (even well written code) and come with a comparably long tail of accumulated historical baggage.
- pjmlp 9y agoHaskell, Common Lisp, Ada, Scala, OCaml, F# come to mind. Even Java and C# are slowly getting down that path. Languages get those features because they make sense and solve real production problems.
- 72deluxe 9y agoYes universal references take a while to understand. I read Scott Meyer's book and the chapter dedicated to it took some getting used to, and note taking. The language is dealing with some tricky concepts. To hide them or try to gloss over them would lead to writing virtual machines and bloated memory usage etc. in the style of C# / Java. How else would you deal with movement of variables and when an rvalue becomes an lvalue inside a function?
- billfruit 9y agoOn the other hand, large C code bases are a special kind of hell, lack of namespaces and user-defined types make it difficult to understand, modify and test.
- carapace 9y agoBut we're discussing a microkernel, not a large C code base, yes?
- johannes1234321 9y agoWe're discussing an operating system with a microkernel in it's heart and many things built around.
- sedachv 9y ago> On the other hand, large C code bases are a special kind of hell, lack of namespaces Can you please name a project that you have worked on where you have run into problems because everything was in a single namespace? What was the problem, how did you run into it, and how did you resolve it? There are a lot of advantages to namespaces. I used to believe that single-namespace languages would cause problems for large software, but working with Emacs (huge single namespace with all the libraries loaded into memory at once, so much worse than C, where you only link a subset of libraries), this problem has not surfaced. I mean literally the only difference is that ".", or whatever the language-enforced namespace accessor is, goes from being special syntactically, to being a convention. When you start to think about namespaces as trees, this makes more sense. Namespaces just push naming conflicts to the parent node. There is no magic that is going to solve conflicts or structure things well or give things clear names. All that is up to the programmer.
- netheril96 9y ago> Since you mentioned error handling as a reason to choose C++, what else could you possibly mean? I believe he means RAII. It makes it almost impossible to forget to release resources or rollback transaction.
- hawski 9y agoI understand RAII as resource management solution. What use does RAII have in error handling? It makes things convenient, but it does not make error handling go away.
- pjmlp 9y agoNo, but exceptions aren't the only way to handle errors in C++. There are also library types that enforce checking for errors, something currently impossible in C. Also thanks to its stronger type system, it is possible to do type driven programming thus preventing many errors to happen at all, which is also not possible in plain C. Finally everyone is moving to C++, C for OS development is stuck on UNIX and embedded devs that wouldn't use anything else even at point gun.
- varjag 9y agoC++ has shrunk a lot in the mindshare since its peak in mid-90s. And Rust is the trendy thing now in the same space.
- pjmlp 9y agoOnly if we are speaking about enterprise CRUD apps that used to be done in MFC, OWL, VCL, Motif++. OpenCL lost to CUDA because it did not natively supported C++, only when it was too late. NVidia has designed Volta specifically to run CUDA C++ code. There is no C left on game consoles SDKs or major middleware engines. All major C compilers are written in C++. Microsoft has replaced their C runtime library by one written in C++, exposing the entry points as extern "C". Beyond the Linux kernel, all native parts on Android are written in C++. The majority of deep learning APIs being used from Python, R and friends are written in C++. Darwin uses a C++ subset on IO Kit, and Metal shaders are C++14. AUTOSAR has updated their guidelines to use C++14 instead of C. All major modern research OSes are being done in C++, like Genode. Arduino Wiring and ARM mbed are written in C++. As for Rust, while I do like it a lot, it still cannot compete with C++ in many key areas, like amount of supported hardware, GUI frameworks and available tooling.
- kllrnohj 9y ago> All of the memory you describe for other purposes is allocated at user level and booked to processes. No, they aren't. A microkernel is responsibe for basic thread management and IPC. Both of which are highly dynamic in nature. You seem to be confusing the system that decides when to make a scheduling decision (userspace process - although still part of the microkernel project, so still included in all this anyway), with the system that actually executes that decision (the microkernel itself). And in the case of systems like QNX the kernel will even do its own decisions independent of the scheduler service, such as switching the active thread on MsgSend. But whether or not it's in ring0 or ring3 is independent of whether or not it's part of a microkernel. A microkernel delegates responsibility to ring3 processes, but those processes are part of the microkernel system - they are in fact a very critical aspect of any microkernel project, as without them you end up building a bootloader with aspirations of something bigger than a kernel.
- naasking 9y ago> A microkernel delegates responsibility to ring3 processes, but those processes are part of the microkernel system I disagree. Certainly you won't get a usable system without some core services, but the fact that you can replace these services with your own as long as you satisfy the protocol means there's a strong isolation boundary separating them from the kernel. Certainly they are essential components of the OS, just not the kernel. As for the alleged dynamism of thread management and IPC, I don't see how it's relevant. There exist asynchronous/non-blocking IPC microkernel designs like VSTa and Minix in which the kernel allocates and manages storage for asynchronous message sends, but it's long since proven that such designs are hopelessly insecure. At the very least, it's trivial to DoS such a system. Only bounded message sends with send/receive buffers provided by processes can you avoid this inevitability. If the idea with Fuchsia is to reimagine consumer operating systems, avoiding the same old mistakes seems like a good idea. As for scheduling, that's typically part of the kernel logic, not a user space process. Yes, message sends can donate time slices/migrate threads, but there are priority inversion problems if you don't do this right, as L4 found out and avoided in the seL4 redesign. I honestly don't know why Google just didn't use or acquire seL4 for Fuchsia.
- TheRealDunkirk 9y ago>The advantages C++ has for application-level programming are useless in this domain. ESR was recently making some generalized observations in this direction: http://esr.ibiblio.org/?p=7804 http://esr.ibiblio.org/?p=7804
- jmaygarden 9y agoHere’s a few of my personal favorite insane nostalgics: * Donald Knuth: http://tex.loria.fr/litte/knuth-interview http://tex.loria.fr/litte/knuth-interview * Linus Torvalds: http://harmful.cat-v.org/software/c++/linus http://harmful.cat-v.org/software/c++/linus * Martin Sústrik: http://250bpm.com/blog:4 http://250bpm.com/blog:4
- getcrunk 9y agoI wish I could give you gold
- bb88 9y agoMartin's take is really good, it's a really well thought through blog post.
- blub 9y agoNo it's not, they confuse "undefined behavior" with "hard to analyse behavior" for starters. Exceptions are not UB, but the control flow is totally not obvious. If I were to start a project today, I'd rely heavily on optional and result types and use exceptions only for serious errors, when it makes sense to unwind ans start from a clean slate.
- jensa1948 9y agoI don't think it is a good blog post. He first criticises exception handling as undefined behavior which it is certainly not, and then criticises exception handling in general because it decouples error raising from error handling. This is whole point of exception handling because they should be used for non-local errors. Most of the "errors" handled in Martin's projects ZeroMQ and Nanomsg (which are both great libraries btw!) should not be handled as exceptions, as they are not unexpected values but rather states that have to be handled. Here, he uses the wrong tool for the job and criticises the tool. He then criticises exceptions thrown in constructors and favors a init-function style. I never had any problem with this because I follow the rule that there shouldn't be much code in the constructor. The one and only task of a constructor is to establish the object's invariant. If that is not possible, then the object is not usable and the caller needs to react and shall not use the object. In the second series, he first compares apples (intrusive containers) and oranges (non-intrusive containers), and then argues that the language forces him to design his software that way. Basically he argues that encapsulation makes it impossible in his case to write efficient code, and that you have to sacrifice it for performance. However, with C++, you can extract the property of being an object in an intrusive list into a re-usable component, e.g. a mix-in, and then use your intrusive list with all other types. I can't do this in C in a type-safe manner, or I have to modify the structs to contain pointers, but why should they have anything to do with a container at all? Besides that, I think that Martin is a greate programmer who did an amazing job with ZeroMQ. But I have the impression that he is wrong in this case.
- bb88 9y ago> If you want to avoid C++ that's great, but to argue for C over it is insanity rooted in nostalgia. Did you know that code in C++ can run outside of main()? I used to be a C++ believer, and advocated for C++ over our companies use of Java. One day, they decided they wanted to "optimize" the build, by compiling and linking objects in alphabetical order. The compile and link worked great, the program crashed when it ran. I was brought in to figure it out. It turned out to be the C++ "static order initialization fiasco": https://yosefk.com/c++fqa/ctors.html#fqa-10.12 https://yosefk.com/c++fqa/ctors.html#fqa-10.12 If you've ever seen it, C++ crashes before main(). Why? Because ctors are getting run before main(), but before other dependent statics have been constructed. Changing the linking order of the binary objects fixed it. Remember nothing else failed. No compiler or linker errors/warnings at the time, no nothing. But one was a valid C++ program and one was not. You might think that is inflammatory, but I considered that behavior insane, because main() hadn't yet even run, and the program cored leaving me with trying to figure out what went wrong. >> Furthermore, you don't want exceptions in kernel code. >Nobody said anything about C++ throw/catch exceptions. I'd like to add that if you're finding yourself restricting primary language features (e.g. templates, statics ctors, operator overloading, etc.) because the implementation of those features are bad, maybe using that language is the wrong choice for the project you're working on. After I read the C++ FAQ lite [1] and the C++ FQA [2], I realized the determinism that C provides is kind of a beautiful thing. And yes. For a kernel, I'd argue C over C++ for that reason. [1] C++ FAQ Lite: http://www.dietmar-kuehl.de/mirror/c++-faq/ http://www.dietmar-kuehl.de/mirror/c++-faq/ [2] C++ Frequently Questioned Answers: https://yosefk.com/c++fqa/ https://yosefk.com/c++fqa/
- gmueckl 9y agoWell, if your main argument against C++ is undefined order of static initialization amd that it caught you by surprise, then I'd counter that by saying that you do not know the language very well. This is very well known behaviour. I think that there are stronger arguments against C++: the continued presence of the complete C preprocessor restricting the effectiveness of automatic refactoring, the sometimes extremely cumbersome template syntax, SFINAE as a feature, no modules (yet!)... Still, C++ hits a sweet spot between allowing nasty hardware-related programming hacks and useful abstractions in the program design.
- omarforgotpwd 9y agoWhat are you talking about... Why would you write a kernel in C++ instead of C? You want fine grained control over what the machine is doing. Imagine dealing with all that bullshit C++ comes with when trying to write a kernel. And then you’re trying to figure out if this C++ compiler you need for this architecture supports dark matter backwards recursive template types but it only supports up to C++ 76 and you’re just like fuck my life
- mlashcorp 9y agoNever has man so eloquently expressed the frustration of millions (OK maybe thousands). The trick to use C++, is to use less of it. C with classes and namespaces. Oh and smart pointers.
- brann0 9y agoYou may know this already: https://gist.github.com/bkaradzic/2e39896bc7d8c34e042b https://gist.github.com/bkaradzic/2e39896bc7d8c34e042b
- jensa1948 9y ago"Orthodox C++" looks more like writing C-code and keeping the C programming style. Most of the points are really questionable. - "In general case code should be readable to anyone who is familiar with C language". Why should it? C++ is a different language than C. I speak german, but I cannot read e.g. French unless I learned it even though they are related. - "Don't use exceptions". Why? There is no performance penalty in the non-except case, and the exception case should be rare because it is exceptional. I can see arguments for real-time systems, and for embedded systems were code size matters. The alternative is C-style return codes and output parameters. Exceptions are better in that case because you cannot just go on after an error condition, and functions with output parameters are harder to reason about because they loose referential transparancy. Of course, in modern C++ one could use optional or expected types. - "Don't use RTTI". I never needed RTTI in my professional life. - "Don't use C++ runtime wrapper for C runtime includes". C++ wrappers have some benefits over the C headers. They put everything in namespace std, so you don't need to use stupid prefixes to prevent name clases, and they define overloads for some of the C functions, e.g. std::abs(int) and std::abs(long) instead of abs(int) and labs(long). - "Don't use stream, use printf style functions instead". If this means to use a type-safe printf variant I could agree to some point, although custom operator(<<|>>) for custom types are sometimes nice. If it means to use C printf etc I would strongly object. - "Don't use anything from STL that allocates memory, unless you don't care about memory management". You can use allocators to use e.g. pre-allocated storage. The STL also contains more than containers, why would you not use e.g. the algorithms and implement them yourself?