29

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
  • 2,847
  • 5
  • 31
  • 51
  • 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

29

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
  • 8,903
  • 4
  • 31
  • 45
  • 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
27

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
  • 63,860
  • 19
  • 125
  • 201
  • 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
15

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
  • 488
  • 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
  • 1
    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
  • 2
    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
  • 8
    @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
10

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,518
  • 3
  • 35
  • 39
  • 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
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,128
  • 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
  • 46,382
  • 17
  • 102
  • 175
  • 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
-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
  • 479
  • 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