5 ms·
Using C++ for kernel development means you first have to drop most of the useful parts of C++ and take usability hits with almost all the other features. Rust
by zaarn 8y ago
Using C++ for kernel development means you first have to drop most of the useful parts of C++ and take usability hits with almost all the other features.
Rust and C have an advantage because both are fairly close to the metal, Rust in no_std mode isn't much different than C but the compiler is angry at you all the time.
- mehrdadn 8y ago> Using C++ for kernel development means you first have to drop most of the useful parts of C++ and take usability hits with almost all the other features. What? No... the most useful parts of C++ are its compile-time facilities... templates and type utilities and RAII/smart pointers/etc. (I could go on and on) all of which are still there. You'd lose some runtime stuff like the ability to throw exceptions and some RTTI, which some people already advise each other to avoid in user mode too (not to say I agree, but they're still finding a lot of use in C++ without this). If losing those is equivalent to losing most of C++ for you then you're not really taking advantage of C++ to begin with.
- DowsingSpoon 8y ago>Using C++ for kernel development means you first have to drop most of the useful parts of C++ and take usability hits with almost all the other features. This is commonly accepted wisdom, but it's not entirely true. (It's only a little bit true.) The kernel is a freestanding environment where big chunks of the standard library are missing. However, the most useful parts, like unique_ptr<T>, can be reimplemented as needed. The kernel absolutely can support RTTI and exceptions. Porting libcxxrt is relatively simple, for example, even if implementing the entire Itanium C++ ABI is a big task. Though, the kernel should still avoid throwing and catching exceptions in sensitive code like interrupt handlers. This is not radically different from other C++ projects. The use of exceptions is typically discouraged, for example, in tight inner loops. It is true that enabling RTTI and exceptions causes code size to explode. This is a valid concern. While memory is cheap, cache misses are not cheap. Mark functions and methods with "noexcept" as needed where this becomes a problem. Finally, it's absolutely true that exceptions make it impossible for the kernel to make solid real-time guarantees. Fortunately, most operating systems only have soft real-time constraints, if that.
- Ar-Curunir 8y ago> Rust in no_std mode isn't much different than C This isn't really true; you still have memory safety, and generics and a sane stdlib.
- zaarn 8y agoMemory safety flies out the window when you write a kernel and the stdlib isn't available in no_std mode. You only get a very limited subset in the core lib. Memory safety in kernels is hard because you might have to do things like switch stack or even address space and the rust compiler handles such actions rather poorly. Whether or not writing to the rsp register will crash the kernel or successfully pivot the stack is guesswork at best and only works reliably if you code it entirely in inline assembly.
- pjmlp 8y agoMemory safety in kernels is also welcomed and is very present in mainframe OSes and high integrity systems where human lives are at stake. Yes, there are a couple of areas where unsafety is required, there isn't any other way. However 100% of the kernel source code doesn't need to be unsafe.
- zaarn 8y agoThere is two types of memory safety that you talk about there, I think. One is the memory safety that the rust compiler wants to hold and the other is the memory safety you program into a system. Those can be entirely different with incompatible guarantees, depending on the mission statement of the software. Some things a kernel must do are unsafe for the rust compiler. Dereferencing a null pointer, for example, is basically a crash in most operating system's userland. In kernel space a null pointer may be valid memory that points to real data you need to use. Setting the page tables is unsafe as well; it's almost impossible to guarantee that the following instructions can run in a static manner. You have to validate the page tables you're about to load at runtime and even then the result could be a process crashing.
- MrBuddyCasino 8y ago
- estebank 8y ago> Rust and C have an advantage because both are fairly close to the metal, Rust in no_std mode isn't much different than C but the compiler is angry at you all the time. Those things the compiler is angry about? Those are things that would be runtime errors in C. `rustc` is pedantic because it needs to be in order to provide the assurances it gives. There is a subset of "valid" Rust code that `rustc` rejects because it isn't smart enough to understand it would be safe, but I would guess that those cases are less common than than the cases of "seemingly valid" Rust code that is in reality problematic if it were accepted. Beyond that, I would like to hear what errors have made you feel like the compiler "is angry" at you instead of feeling the compiler "is trying to help me". We spend an inordinate amount of effort on 1) accepting code that we should accept by improving ergonomics, 2) provide extensive suggestions when "seemingly correct" code hits the wall of `rustc`'s understanding, language design or things addressable by ergonomics, and 3) provide as good explanations as possible for all other cases. Because of this, I believe the experience of a newcomer today is much better than even a year ago, even though it can still be improved.
- zaarn 8y ago>Those things the compiler is angry about? Those are things that would be runtime errors in C. I'm very very aware of that though this is not always true. For example Rust doesn't have a sane way to have a reentrant mutex without including std, which is bad because for interrupts in a kernel you need to either have very fine grained locking and fallbacks or rely entirely on lockless operations. Interrupts can occur on top of eachother in which case it behave a lot worse than simply being reentrant. rustc yells at me a lot for the solutions this requires because the way I solve it violates ownership rules of rust the hard way to make the code simpler and understandable. Other times it's when for bizarre reason rust wants the code to implement the Sync and Send traits despite the kernel running alone on the core (there is no threading in that kernel) and I would love to be able to tell rustc to just shut up about this and simply ignore Send, possibly even Sync, on a module level.
- richardwhiuk 8y agoLinux's kernel runs on more than one core and is pre-emptible, so that's just not generally true.