30

From what I know, even though the common OS have parts written in other languages, the kernel is entirely written in C.

I want to know if it's feasible to write a Kernel in C++ and if not, what would be the drawbacks.

Community
  • 1
  • 1
coredump
  • 3,017
  • 6
  • 35
  • 53
  • A very balanced analysis of possibly using C++ for the Linux kernel can be found here http://thread.gmane.org/gmane.comp.version-control.git/57643/focus=57918. – Benjamin Bannier Sep 12 '12 at 09:52
  • 23
    @honk: "From: Linus Torvalds"... yeah, balanced... – avakar Sep 12 '12 at 09:53
  • 2
    @honk Ok.That's Linus opinion, but I mean if now someone would start to develop a kernel, would C++ would be such a bad choice? and regarding to some issues that Linus pointed out, you could just ignore the STL and Boost and just develop your own classes. – coredump Sep 12 '12 at 09:58
  • 4
    The [LKML FAQ item #15.3](http://www.tux.org/lkml/#s15-3) is my number one example of badly done propaganda that any high-schooler should be able to see through. Circular reasoning, straw-man arguments and very nice "find / wc" logic to prove the "nightmare" that it would be to write a couple of "find / sed"s. They either don't *want* or don't *know* C++, and that's fine, but they shouldn't be spewing all that BS about it. – DevSolar Sep 12 '12 at 10:02
  • 5
    http://msdn.microsoft.com/en-us/library/windows/hardware/gg487420.aspx can be read in a general sense to get an understanding of some of the issues. – ta.speot.is Sep 12 '12 at 10:15
  • @ta.speot.is That's a must-read. – Alexey Frunze Sep 12 '12 at 10:43
  • 6
    @coredump: I am developing in-house kernel components in C++ for many years now. There are places where you have to be careful, but otherwise it is even easier than C since you can use raii for critical cleanup stuff and similar (reference counting is easier to handle too). – PlasmaHH Sep 12 '12 at 11:11
  • @DevSolar kernel development is 100% implementation dependent code. It _implements_ the memory model, it works with specific binary representation of data, it works with hardware, interruptions, data punning. If you're not aware, C++ standard ether bans some of those things or does NOT define what would happen if someone dwells there. Thus are difference in data initialization and handling between C and C++, C++ is abstract in relation to memory model or data implementation. – Swift - Friday Pie Jan 02 '17 at 09:45
  • 2
    @Swift: Oversimplified blanket statement. And you came back on a comment four years and something old for that? – DevSolar Jan 02 '17 at 09:54

9 Answers9

30

There are plenty of examples of well-used operating systems (or parts of them) implemented in C++ - IOKit - the device driver subsystem of MacOSX and IOS is implemented in EC++. Then there's the eCOS RTOS - where the kernel is implemented in C++, even making use of templates.

Operating systems are traditionally awash with examples of OO concepts implemented the hard way in C. In the linux device model kobject is effectively the base-class for driver and device objects, complete with DIY v-tables and some funky arrangements implemented in macros for up and down-casting.

The Windows NT kernel has an even more deeply rooted inheritance hierarchy of kernel objects. And for all of the neigh-sayers complaining about the suitability of exception handling in kernel code, exactly such a mechanism is provided.

Traditionally, the arguments against using C++ in kernel code have been:

  • Portability: availability of C++ compilers for all intended target platforms. This is not really an issue any more
  • Cost of C++ language mechanisms such as RTTI and exceptions. Clearly if they were to be used, the standard implementation isn't suitable and a kernel-specific variant needs using. This is generally the driver behind the use of EC++
  • Robustness of C++ APIs, and particularly the Fragile base-class problem

Undoubtedly, the use of exceptions and RAII paradigm would vastly improve kernel code quality - you only have to look at source code for BSD or linux to see the alternative - enormous amounts of error handling code implemented with gotos.

marko
  • 9,029
  • 4
  • 30
  • 46
  • Ummm no, you have a possible case for templates and other parts of c++, but you have no case for exceptions in a kernel... when the kernel exists to provide the runtime those very exceptions require. – J. M. Becker Aug 07 '19 at 15:27
  • 1
    Go and look at the BSD or linux kernel and count the number of `goto` statements and local branch labels littered throughout the code. That is the case for exception handling - which would then allow the RAII idiom to be applied pervasively. As stated, the WindowsNT kernel has an exception mechanism. What you can be sure of is that it's not the user-space exception handling mechanism. – marko Aug 07 '19 at 17:00
29

This is covered explicitly in the OSDev Wiki.

Basically, you either have to implement runtime support for certain things (like RTTI, exceptions), or refrain from using them (leaving only a subset of C++ to be used).

Other than that, C++ is the more complex language, so you need to have a bit more competent developers that won't screw it up. Linus Torvalds hating C++ being purely coincidental, of course.

DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • 3
    From what I know, in many projects actually only a subset of C++ is used. I mean, C++ would make a case in the sense that it could be written like in C, but, when needed, you could use some encapsulation, or some other language features that are harder to get in C ( I mean you could get some kind of classes even in C with function pointers ) . – coredump Sep 12 '12 at 10:04
  • 3
    @coredump: Usually the reason for using a C++ subset is that many hobbyists setting out to develop a kernel of their own simply don't have the in-depth understanding to make full-fledged C++ runtime support feasible yet. Exception handling, for one, is a pretty involved issue, and took the compiler implementors years to get "right" from an efficiency standpoint. Using existing implementations raises the issue of software licensing. Moreover, the stuff that needs runtime support usually involves runtime *costs* as well, and you don't really want that if you can do without. – DevSolar Sep 12 '12 at 10:51
  • @coredump: Oh, and one thing I forgot... things like exception handling aren't implemented *tabula rasa*, but are dependent on the *compiler*... and GCC technical docs aren't a bag of laughs, either. ;-) – DevSolar Sep 12 '12 at 11:35
18

To address Torvalds' concerns and others mentioned elsewhere here: In hard-RT systems written in C++, STL/RTTI/exceptions are not used and that same principal can be applied to the much more lenient Linux kernel. Other concerns about "OOP memory model" or "polymorphism overhead" basically show programmers that never really checked what happens at the assembly level or the memory structure. C++ is as efficient, and due to optimized compilers many times more efficient than a C programmer writing lookup tables badly since he doesn't have virtual functions at hand.

In the hands of an average programmer C++ doesn't add any additional assembly code vs a C written piece of code. Having read the asm translation of most C++ constructs and mechanisms, I'd say that the compiler even has more room to optimize vs C and can create even leaner code at times. So as far as performance it's pretty easy to use C++ as efficiently as C, while still utilizing the power of OOP in C++.

So the answer is that it's not related to facts, and basically revolves around prejudice and not really knowing what code CPP creates. I personally enjoy C almost as much as C++ and I don't mind it, but there is no rational against layering an object oriented design above Linux, or in the Kernel itself, it would've done Linux a lot of good.

SeventyFive
  • 527
  • 4
  • 7
  • 1
    You miss the point completely, You WILL create/use leaky abstractions and extra features to make otherwise poor implementation choices. In fact, I've NEVER seen a c++ project at that low level that wasn't later recognized as a stupid management driven choice. Your code will be written down faster, and that's what they care about ROI.. But from a systems only perspective, Your adding systemic risk, and your basically saying expertise can compensate. In the real world, no it can't, because expertise is a limited resource. Thus what could happens, eventually always happens after enough time. – J. M. Becker Jul 20 '16 at 18:55
  • Wan't a real world example? The guy who wrote ZeroMQ now deeply regrets writing this low level systems library in C++. C++ for your game? Great. Your desktop application? no problem. Don't get that poison anywhere near a systems level library, I wouldn't even use it, the fact it was written in C++ AT ALL tells me nobody gave two sh*ts about the implementation. Yea it's like that. Linus speaks from HARD EXPERIENCE about what happens when your theory and practice diverge. Anyone who doesn't know this? I wouldn't want them near a project either. They are meant for higher level code. – J. M. Becker Jul 20 '16 at 18:58
  • 5
    @TechZilla Sounds like some zealous, communal reinforcement, "No Trust Scotsman" trolling. I've used Rust, SPARK, C++ and C bare metal and they have their strengths and weaknesses. A strict subset of C++ (consider the costs/risks of supporting RTTI, templates, exceptions, std, allocator, etc.) with enforced conventions is definitely workable and has better namspacing. –  Aug 25 '17 at 02:23
  • @berry, this isn't any such fallacy, this is the real world, when imperfect people use tools far more powerful than they should be for such low level work. Rust, I have higher hopes for than C++, but thus far it still needs more work to be able to replace C. – J. M. Becker Aug 27 '17 at 19:48
  • 8
    @TechZila I read the asm, but you don't have to, Scott Meyers gives a novice friendly help for CPP novices on these subjects. 1) Leaks are VASTLY more common in C, since polymorphism (that plagues the Kernel code) is done with lookup tables, and pointer hell is all over C open source until it matures. 2) Extra features are never added by C++, you have to explicitly specify them. 3) Many military Hard RT systems use C++, in fact I gave lectures on RT C++ in the place that created Iron Dome in Haifa. Many medical Hard RT is the same way. – SeventyFive Sep 02 '17 at 16:52
  • 3
    4) Expertise? Don't use STL containers, don't write "virtual" when you don't need it (minor impact), don't use RTTI. Done. 5) If you use functors you can exceed C's performance in the common case of passing function pointers, as functors can be inlined when passed. 6) Gaming's demands are stricter than the Linux Kernel, don't condescend them, and reliability of systems mentioned in item 3 in my previous comment, is more demanding. 7) Sorry, but at the time Linus made his decisions on CPP vs C, he had less C++ knowledge than most of the gurus in this very site. – SeventyFive Sep 02 '17 at 17:02
  • 3
    So efficiency is equal and better (Meyers book can assist here) and knowledge req is low (see items 4 & 5 in my prev comment) Reliability (item 1), is incomparable if only just due to C forcing you to use lookup tables' pointers for the Kernel pervasive polymorphism, but that is just one example of imitating C++ in C, others are unreadable macros. We're just scratching the surface here. Look, I held the same disbelief 14 years ago when I switched to C++ after 6 years in Hard RT C, now I only use C when uploading to a C open source. Don't be religious, read Scott Meyers, he's a good starter – SeventyFive Sep 02 '17 at 17:21
  • @seventyfive, I'm not being religious, you're being utopian. I never asserted it is technically inferior to use C++, but explaining why we see quality problems in C++ projects. The tool is simply too powerful, the shortcuts too enticing, maintaining quality becomes a serious problem. – J. M. Becker Sep 03 '17 at 14:17
  • 9
    @TechZilla: I have written numerous projects in both C and C++. And I **cringe** every time I have to revert to manual memory management, return-code checking and cleanup procedures in C. If C++ had nothing to offer but constructors, destructors, and ``, I'd take it. And most of the work I've done over the last 15 years in the business has been *reimplementing* C code (or really poor C++ code written by C / Java coders who didn't understand the differences) in C++ to make it *more* maintainable. I blame instructors, online tutorials, and "trial & error" mentality, not the language. – DevSolar Sep 13 '17 at 10:00
  • @J.M.Becker, _I'm not being religious_ and _The tool is simply too powerful_ are really contraddictory statements, ahahah. The latter sounds the claim of somebody from a cult that prohibits innovation and nurtures fear. – Enlico May 25 '23 at 22:37
  • @Enlico, You practically admitted the exact problem I outlined, C++ requires expertise beyond what otherwise reasonably competent programmers have. I also blame instructors, crappy tutorials that fail to impart actual knowledge and instead provide how to examples.... but it doesn't change the conditions. It requires specialized knowledge, and at the lowest levels, it just isn't an ideal choice because how things should be done are not the same as the best practices used in more typical situations. – J. M. Becker Jun 17 '23 at 17:17
  • @Enlico The point is, if you know C++ implementation very well, you can use it for a low level systems project, but you need to actually know that or you will create a mess. It's not like how people normally know a programming language, which comes with practice and writing code, its straight up implementation knowledge. – J. M. Becker Jun 17 '23 at 17:31
  • @Enlico Your statement, " Don't use STL containers, don't write "virtual" when you don't need it (minor impact), don't use RTTI. Done.", is NOT enough. Zircon's codebase almost looks like C code, it looks that way for a reason, that's more than some lines about not using a few features. We don't even know if it works well enough either, last I tested it it did not perform. The fact that the codebase wasn't written by a small team, almost assures failure. – J. M. Becker Jun 17 '23 at 17:51
  • @J.M.Becker, I think that was not me :D – Enlico Jun 18 '23 at 15:25
  • @DevSolar Comments were intended, tagged wrong author – J. M. Becker Jun 27 '23 at 17:38
  • @J.M.Becker And you really think I'd be interested in a six-year necro rant, given how aggressive your *first* comment was? I'm not interested in wasting my time. Keep coding C if you like. – DevSolar Jun 27 '23 at 21:03
9

You can write an OS kernel in more or less any language you like.

There are a few reasons to prefer C, however.

  • It is a simple language! There's very little magic. You can reason about the machinecode the compiler will generate from your source code without too much difficulty.
  • It tends to be quite fast.
  • There's not much of a required runtime; there's minimal effort needed to port that to a new system.
  • There are lots of decent compilers available that target many many different CPU and system architectures.

By contrast, C++ is potentially a very complex language which involves an awful lot of magic being done to translate your increasingly high-level OOP code into machine code. It is harder to reason about the generated machine code, and when you need to start debugging your panicky kernel or flaky device driver the complexities of your OOP abstractions will start becoming extremely irritating... especially if you have to do it via user-unfriendly debug ports into the target system.

Incidentally, Linus is not the only OS developer to have strong opinions on systems programming languages; Theo de Raadt of OpenBSD has made a few choice quotes on the matter too.

Rook
  • 5,734
  • 3
  • 34
  • 43
  • 10
    C isn't simple. It has a pretty complex and ugly and error-prone declaration grammar (ever misplaced `const` or `volatile` when declaring pointers to pointers?). Its type system and promotions are another pain for every novice (and for pros, too, at times). It's got a number of undefined, unspecified and implementation-specific behaviors, yay, more magic (=surprises)! Floating point, albeit not used a lot in the kernels, is another problematic area. Assembly language, in comparison, is much more direct and in a way simpler, less surprising. – Alexey Frunze Sep 12 '12 at 10:40
  • 15
    Conversely, in C-based kernels we see DIY implementations of OO concepts - a considerable amount of wheel re-invention that one would get for free from using C++ in the first place. This is a very real code quality issue as it results in far more complexity, particularly in error paths that are unlikely to receive proper testing. – marko Sep 12 '12 at 10:45
  • 1
    @AlexeyFrunze: and yet almost everything else, (with the exception of assembly, granted) is _more_ complex and _more_ magic and hence provides more ways for problems to arise. As a portable assembly language, C is pretty reasonable. There have been numerous attempts to make a "better" systems programming language, but I'm not personally aware of any that have made it out of the academic project stage. – Rook Sep 12 '12 at 10:51
  • 2
    @Marko: indeed, it is difficult for many developers to cope without their familiar layers of abstraction, and the resulting hacks are often awful because they are not language developers. Abstraction is valuable in higher level applications, but not when you are coding close to the metal. An undisciplined coder can write rubbish in any language; it is not the fault of the language that it lets them do so. – Rook Sep 12 '12 at 10:54
  • Don't get me wrong. C is great and I love it for its powers despite all of the shortcomings. Though, one could make a better C by reducing the number of surprises it has. Many are unreasonable by today's "standards" and only exists because of compatibility and historical reasons. – Alexey Frunze Sep 12 '12 at 10:59
  • @AlexeyFrunze: I think we can all agree on that; it does seem that C's ubiquity and historical inertia make it unlikely that a decent improvement or replacement will arise and become dominant (or even popular) any time soon, unfortunately. – Rook Sep 12 '12 at 11:06
  • @Rook Your comment aged as well as Rust – Default Aug 06 '20 at 14:29
  • 1
    @Rook As "The Story of Mel" reminds us, assembly language programmers waste cycles because they can't handle machine code. If abstraction wasn't valuable, why are you forcing yourself to go through a function header, when sometimes you can save time jumping directly to the middle of a function? (Yeah, that was done in the old days.) Why all this fuss about types when they're all 64 bit long? (Neither assembly nor BLISS care whether you put an integer or a pointer in that register, while C forces you to declare it and explicitly cast it.) C has plenty of abstractions from the hardware. – prosfilaes Oct 11 '21 at 05:07
  • @prosfilaes types are not all 64 bits long. you can mov a byte, word, dw, quad and the store in memory is reflected on that size: 1,2,4,8 bytes. There is no abstraction if you have an overflow on a byte is because you are using a 8 bit register and its operation on a 8 bit register for e.g: `mov al, 0xFF; add al, 1` => C types represents this. function headers are required by compilers and linkers. can it be done without the include files? it can, but it is a different compilation life-cycle also for generating lib/shared objects. – Raffaello Jan 18 '23 at 10:02
  • @Rook not sure you can use any language, at first it's needed a language that generates machine code, then requires hardware I/O support and finally some specific CPU instructions required for Ring 0, so worst case must support "ASM snippets" of code. It can't be done this with JS for e.g nor a garbage collected Language, totally Ring 3, OS Runtime dependent languages – Raffaello Jan 18 '23 at 10:09
  • 1
    @Raffaello Depends on the system, but in x86 you can treat them as byte, word, dw and quad instead of integers and pointers and floating point numbers. Why are you adding that abstraction? Compilers, linkers and shared objects all add abstractions. Any language can be compiled to machine code, and even if there's not ASM snippets, that's a frequent addition, or assembly can be linked in in external functions. (Note that standard C doesn't support inline assembly.) Microsoft researchers have written kernels in garbage collected languages, like Singularity. – prosfilaes Jan 19 '23 at 01:29
  • I respectfully disagree with the claims in this answer: 1) C++ is simpler. Consider a lookup table for funcs, which in C++ would translate to polymorphism, without pointers or untraceable logic. Consider MACROs that would be templates/constexpr that are clearer and less buggy, etc 2) C++ is faster in practice, as the flexibility I presented causes programmers to use static ops more, and compilers have more knowledge for optimization. Also a C funcptr cannot be inlined, a functor can. 3+4) Same coverage and portability. The problem is outdated open-source rules, we need to change that. – SeventyFive May 26 '23 at 23:45
4

The feasibility of writing a kernel in C++ can be easily established: it has already been done. EKA2 is the kernel of Symbian OS, which has been written in C++.

However, some restrictions to the usage of certain C++ features apply in the Symbian environment.

otto
  • 1,138
  • 6
  • 14
2

While there is something "honest" about (ANSI) C, there is also something "honest", in a different way, about C++.

C++'s syntactic support for abstracting objects is very worthwhile, no matter what the application space. The more tools available for misnomer mitigation, the better ... and classes are such a tool.

If some part of an existing C++ compiler does not play well with kernel-level realities, then whittle up a modified version of the compiler that does it the "right" way, and use that.

As far as programmer caliber and code quality, one can write either hideous or sublime code in either C or C++. I don't think it is right to discriminate against people who can actually code OOP well by disallowing it at the kernel level.

That said, and even as a seasoned programmer, I miss the old days of writing in assembler. I like 'em both ... C++ and ASM ... as long as I can use Emacs and source level debuggers (:-).

David Elson
  • 211
  • 2
  • 3
1

Revision after many years:

Looking back, I'd say the biggest problem is actually with the tons of high level features in C++, that are either hidden or outside the control of the programmer. The standard doesn't enforce any particular way of implementing things, even if most implementations follow common sanity, there are many good reasons to be 100% explicit and have full control over how things are implemented in a OS kernel.

This allows (as long as you know what you are doing) to reduce memory footprint, optimize data layout based on access patterns rather than OOP paradigms, thus improve cache-friendliness and performance, and avoid potential bugs that might come hidden in the tons of high level features of C++.

Note that even tho far more simple, even C is too unpredictable in some cases, which is one of the reasons there is also a lot of platform specific assembly in the kernel code.

dtech
  • 47,916
  • 17
  • 112
  • 190
  • 5
    Since we're comparing C++ and Java already, I think it's also worth emphasising that OOP is not the same as "everything is one polymorphic hierarchy". To me, `unique_ptr` is as much a use of OOP as is, say an abstract factory singleton wrapper bean. Perhaps even more so. – Kerrek SB Sep 12 '12 at 10:03
  • 1
    Java was just an example of a language that enforces OOP, no comparison intended at all. And sure, OOP is a big paradigm that can take many forms (pun intended) - I just mentioned what decreases performance and this is unsuitable for use in performance critical scenarios. – dtech Sep 12 '12 at 10:14
  • 2
    The question is about C++, not OOP. C++ has many features that have little to do with OOP (and I care to disagree with @KerrekSB on this). – Fred Foo Sep 12 '12 at 10:36
  • @larsmans yes, the reason I decided to talk about OOP is because it is the main differentiation from C, and no one else seems to have mentioned its performance flaws. – dtech Sep 12 '12 at 10:39
  • 2
    It's the original difference, but by no means still the main one, and I don't think the performance hit matters -- it would be replacing dispatched calls that are already common in kernel code. (The -1 is not from me, btw.) – Fred Foo Sep 12 '12 at 11:21
  • 6
    OOP isn't the main difference, it is things like templates, stronger type checking, overloaded functions, namespaces, and classes with member functions for better abstractions. Nothing of which affects performance, or suitability for kernel use. – Bo Persson Sep 12 '12 at 11:41
  • @BoPersson - exactly, those do not affect performance, and compile time penalties are not critical in that particular case. – dtech Sep 12 '12 at 12:26
  • 7
    The argument here that polymorphism in C++ carries a run-time penalty ignores the fact that kernels implemented in C are absolutely full of DIY vtables and polymorphic function calls. – marko Sep 12 '12 at 13:01
  • @Marko - I haven't dug into kernel source myself, but if I develop a performance critical routine I'd stay away from polymorphism as much as possible, be that "stock" or DIY. Surely, there are the cases it is inevitable, but there are also those, which can be avoided. – dtech Sep 12 '12 at 13:14
  • 1
    @ddriver the vast majority of the work a kernel does is not particularly performance critical - but instead could be classified as a data-structure heavy computing task. – marko Sep 12 '12 at 16:51
  • @ddriver Code that works with hardware cannot be abstract by definition. Or you suggest that we move level of HAL to firmware? That would be very special platform. Again, then firmware will be written in C 9as it usually is). Which was a case of Symbian OS mentioned here, "the kernel" there was relying on hardware level of abstraction. – Swift - Friday Pie Jan 02 '17 at 09:54
1

Google's new-coming operating system Fuchsia is based on the kernel called Zircon, which is written mostly in C++, with some parts in assembly language[1] [2]. Plus, the rest of the OS is also written mostly in C++[3]. I think modern C++ gives programmers many reasons to use it as a general programming environment for huge codebases. It has lots of great features, and new features are added regularly. I think this is the main motive behind Google's decision. I think C++ could easily be the future of system programming.

omergoktas
  • 11
  • 2
  • 1
    Up and coming for quite some time now, and the confirmation will be when the OS demonstrates performance within adequate bounds... it's still not there yet, and the longer this goes on, the less likely it gets there. – J. M. Becker Jun 17 '23 at 17:48
-6

One of the big benefits of C is it's readability. If you have a lot of code, which is more readable:

foo.do_something(); 

or:

my_class_do_something(&foo); 

The C version is explicit about which type foo is every time foo is used. In C++ you have lots and lots of ambiguous "magic" going on behind the scenes. So readability is much worse if you are just looking at some small piece of code.

user2826084
  • 517
  • 5
  • 11
  • 7
    Completely contrived example to make a doubtful point. Besides, which of the two examples is C, which is (your idea of) C++? – DevSolar Feb 09 '16 at 14:20
  • BTW, C++ is even more strict to type safety and types conversion than C! – Alex D Oct 19 '17 at 21:17