46 ms·
Upcoming Rust language features for kernel development
- hannesfur 1y agoThese seem like the first features that Rust in Linux bring to the Rust language that are not almost exclusively useful to the kernel. In my perception the focus on bringing features for the kernel has held up development in other parts of the language and the standard library.
- oersted 1y agoAs I understand it systems programming is the priority application area for Rust, and there are plenty of projects working on OSs, embedded or other bare-metal cases, as well as interoperability with complex C codebases. At first glance, these features look quite general to me and not particularly tied to the kernel, they are important utilities for doing this kind of programming in the real world.
- heavyset_go 1y agoWhat's the story with C interop now with these and related changes? I'm out of the loop.
- deleted 1y ago[deleted]
- muvlon 1y agoC interop is excellent and has been for years. The one piece that still needs unstable is defining/exposing varargs functions (support for calling them was stabilized many years ago). You can write almost anything you can write in C in (partly unsafe) Rust, in fact there are projects like c2rust that automate this translation. These new features are all about making things that the kernel devs need possible in safe Rust. This often requires support for some quite fancy abstractions, some of which cannot be expressed in current stable Rust.
- Foxboron 1y ago> C interop is excellent and has been for years. Only if you primarily work with `cargo` and want to interact with C from Rust. The other way around has far less support and `rustc` does not standardize the object generation. This is actively preventing projects like `systemd` to adopt Rust into their project as an example. https://github.com/systemd/systemd/pull/19598 https://github.com/systemd/systemd/pull/19598
- aw1621107 1y ago> Only if you primarily work with `cargo` and want to interact with C from Rust. In what way(s) does Rust's C interop depend on cargo? > The other way around has far less support and `rustc` does not standardize the object generation. I believe in this context the understanding is that you're going to be using `extern "C"` and/or `#[repr(C)]` in your Rust code, which gives you a plain C interface. I think attempting to use "raw" Rust code from other languages is a rare phenomenon, if it's even attempted at all. > This is actively preventing projects like `systemd` to adopt Rust into their project as an example. Could you point out specific instances from that thread? From a quick glance I didn't see any obvious instances of someone saying that using Rust from C is problematic.
- humanrebar 1y ago> In what way(s) does Rust's C interop depend on cargo? Do rust and cargo allow for multiple interpretations of the same C header file across different objects in the same program? That's how C libraries are often implemented in practice due to preprocessor tricks, though I wish it wasn't normal to do this sort of thing.
- nicoburns 1y agoI would expect so. Rust and Cargo don't consume C header files directly at all. They consume bindings generated by bindgen (or hand written if you prefer). So you could probably generate mulitple bindings if you needed multiple interpretations of a C header. If the header files are consumed by C code that is then consumed by Rust then you'll have full support for what C supports because it will be compiled by a C compiler.
- 3836293648 1y agoIt's C++ that is problematic, C has been easy for years
- heavyset_go 1y agoAre the kernel-related changes applicable to C++ interop? Honest question, I don't know.
- gpm 1y agoThe kernel doesn't use any C++, so no more than incidentally. There is some C++/rust interop in the past that I've worked on that would have enjoyed the arbitrary self types feature, but not particularly because of the C++ part of the equation. In fact I think if it had been a pure rust project it would also have enjoyed that feature just as much so... eh... take it for what little it's worth I guess.
- cyphar 1y agoCalling C code from Rust? Pretty nice. Writing Rust code to be called from C (but within the same application)? Doable but somewhat painful. Writing Rust code to act like a C shared library? Quite painful and some pretty important features are missing (proper symbol versioning support being the most obvious one). Theoretically doable if you're willing to compromise. There's also some aspects of FFI-safety that are very subtle and easy to mess up: * #[repr(C)] enums still have the same requirements as Rust enums and so C callers can easily trigger UB, so you need to use something like open_enum. Thankfully cbindgen is too dumb to know that #[open_enum] is a proc macro and produces a non-enum type. * Before io_safety in Rust 1.63, dealing with file descriptors from C without accidentally closing them was horrific (though this was a wider problem in Rust). BorrowedFd is quite nice -- though Rustix will panic if you use negative fds and so you need to add validation and your own type in practice. However, #[repr(transparent)] is very nice for this. * Lots of reading about unsafe Rust is necessary when doing most non-trivial things with C FFI. * You need to make use of a lot of compiler internals, build scripts, and other magic to get the output you want. * Tools like cargo-c and cbindgen are nice and probably work great for 80% of projects, but the 20% really suffer from no useful tooling. I haven't tried to use rustc directly to work around some of the remaining issues, but I suspect it'd be even more painful. I would say that the C interop with Rust is pretty good but it has lots of room for improvement and it feels like very few resources have been spent on it after they got the core stuff working. Source: I've been writing a Rust library intended to be used primarily via C FFI and run into a lot of issues...
- heavyset_go 1y agoThanks for the info, I've been wanting to use Rust in a project with a lot of FFI going both Rust <-> C ways. Still sounds like it's a bit hairy.
- pjmlp 1y agoI see Rust's place on low level systems programming, for everything else on userspace compiled managed languages are a much better option, systems following an architecture like Self, Inferno or Android, so I don't see a big deal with these efforts focusing on low level C like capabilities.
- timschmidt 1y ago> for everything else on userspace compiled managed languages are a much better option As someone who's written a number of userspace applications in many languages as well as embedded firmwares running on bare metal, Rust is a rare gem that excels at both.
- pjmlp 1y agoOnly if those userspace applications are headless, Rust exceling at GUIs is a bit of a strech.
- timschmidt 1y agoWell https://github.com/timschmidt/egui-rad-builder https://github.com/timschmidt/egui-rad-builder has come together rather well in the last week of hacking, if I say so myself. I think building a similar app with QT, for example, would have been significantly more challenging. I'm particularly fond of how easy it was to make all the controls live in the editor, and editable with changes appearing immediately. imgui would probably provide a similar experience, but I find C++ much more of a pain to work with than Rust.
- mdhb 1y agoBut that’s no longer the choice you need to make. Ubuntu themselves have said for a couple of years now that every new GUI app they make natively for Linux is going to be Flutter and dedicated a bunch of engineers to the project to make sure it’s a first class citizen. Beyond that, Dart / Futter are truly an absolute pleasure to use for that use case.
- junon 1y agoThere are a lot of features being added for kernel/firmware development, they're just not on everyone's radar. Philopp has been a particular force for change in this area.
- PoignardAzur 1y ago> Since the talks described in this article, the work on field projection has received an update. Lossin wrote in to inform LWN that all fields of all structures are now considered structurally pinned, so projecting a Pin will now always produce a Pin<&mut Field> or similar value. Huh, I missed that part. It's a pretty technical point, but I'm happy they made the decision, it held up a lot of discussions.
- PoignardAzur 1y ago> The final design, taking inspiration from C++, would be a form of guaranteed optimization, where constructing a new value and then immediately moving it to the heap causes it to be constructed on the heap in the first place. Note that there's some discussion about the name of that proposal, because "optimization" gives the wrong idea (that it's optional or could depend on the backend).
- dapperdrake 1y agoHow does "coalesced heap construction" or "coalesced heap allocation"?
- Tuna-Fish 1y agoI'm probably misunderstanding the complexity of the problem, but wouldn't this be solvable by just defining the right calling convention? "Any structures larger than x, or any structures marked with a marker type, are returned by the caller providing an outref to a buffer with correct size, and the callee directly writes the structure into that buffer." Then you could just write normal code like fn initialize() -> A { // the initialization code } and it would just work? And it would reduce unnecessary copies in a lot of other situations too? Given how much work has been put into this issue, and how much less convenient the proposed solutions are, I feel like I must be missing something.
- simonask 1y agoThe missing piece is that it would still force you to make even larger types in many cases, such as `Result<Large, Error>`. Essentially the problem is composability. If you are building a large type from a sequence of other large types, and one or more step is fallible, the normal return ABI breaks down very quickly.
- sesm 1y agoWhy make this a behind-the-scene optimization instead of just introducing `new`? That would make things much more clear for everyone.
- kachapopopow 1y agoEverytime features are mentioned it makes me go: "it's all fun and games until someone puts tokio into the kernel", better yet if rust becomes complete enough and someone makes a direct composition renderer we could have entire applications that run entirely in the kernel which could be... interesting.
- aliceryhl 1y agoIt's trivial to implement an async runtime in the kernel. The kernel's workqueue is already essentially a runtime.
- jgilias 1y agoI was about to take offence at the use of “trivial” in this context. But then I noticed your handle, lol. You have the license to say that, thanks for your contributions!
- aliceryhl 1y agoIt never made it into upstream Linux, but there is already a sample implementation that Wedson wrote in 2022: https://github.com/Rust-for-Linux/linux/pull/798 https://github.com/Rust-for-Linux/linux/pull/798
- 3836293648 1y agoWon't that be an eager runtime though? Breaking Rust's assumption that futures do nothing until polled? Unless you don't submit it to the queue until the poll call, I guess
- aliceryhl 1y agoIt won't be different from Tokio. When you pass a future to tokio::spawn, that will also eagerly execute the future right away.
- seabrookmx 1y agoI'm not sure if you're joking, but if not this is a fundamental misunderstanding of how Rust (and C) are used in the kernel. Much like how you don't have the C stdlib when writing kernel code, Rust is used with the no_std option. You do not use cargo and do not have access to crates. You'd likely have to rewrite half of tokio to use kernel level abstractions for things like sockets and everything else that interacts with the OS.
- Jweb_Guru 1y agoAll these features sound really awesome and would also benefit many non-kernel cases (especially generalized projections). Very happy to see Linux driving the language forward.
- rana762 1y ago[dead]
- a-dub 1y ago> The Rust for Linux project has been good for Rust i just decided do a good ol' 'find -name "*.rs"' in the kernel tree to get a sense for what all this is about. from what i can tell, there's just an api compatibility layer (found in /rust) and then a smattering of proof of concept drivers in tree that appear to just be simple rewrites of existing drivers (with the exception of the incomplete nvidia thing) that aren't even really in use. from what i can tell even the android binder rust rewrite is vestigial. the whole thing seems kinda cute but like, shouldn't this experiment in programming language co-development be taking place somewhere other than the source tree for the world's most important piece of software? redox is a pretty cool experimental piece of software that might be the os of the future, why not do it there?
- dmm 1y agoThe gpu driver for Apple silicon is Rust and the author stated it would have been much more difficult to implement in C. It isn't upstreamed yet. """ Normally, when you write a brand new kernel driver as complicated as this one, trying to go from simple demo apps to a full desktop with multiple apps using the GPU concurrently ends up triggering all sorts of race conditions, memory leaks, use-after-free issues, and all kinds of badness. But all that just… didn’t happen! I only had to fix a few logic bugs and one issue in the core of the memory management code, and then everything else just worked stably! Rust is truly magical! Its safety features mean that the design of the driver is guaranteed to be thread-safe and memory-safe as long as there are no issues in the few unsafe sections. It really guides you towards not just safe but good design. """ https://asahilinux.org/2022/11/tales-of-the-m1-gpu/ https://asahilinux.org/2022/11/tales-of-the-m1-gpu/ > the whole thing seems kinda cute but like, shouldn't this experiment in programming language co-development be taking place somewhere other than the source tree for the world's most important piece of software? Torvalds seems to disagree with you.
- remix2000 1y agoRustlang doesn't aim to address race conditions. Sounds to me like overly "cautious" inefficient code you can write in any language. Think using `std::shared_ptr` for everything in C++, perchance…?
- le_app_amour 1y ago[dead]
- shevy-java 1y agoI am scared. More than excited.
- bobajeff 1y agoLooking at the rust rfc for the lightweight clones feature [1]. It took me a while to sort of understand it. Once I did I was excited for the feature but after awhile I was once again struck by the observation that rust is a very complex language to learn. To me as someone who's not learned either it looks like all the concepts and features of 'true' modern C++ (as opposed to C + a few extra features) spliced with the features and concepts of Haskell. Yet people seem to like making useful things in it so it must have gotten something right. So I'll probably get around to attempting to really use it again. [1]: https://github.com/joshtriplett/rfcs/blob/use/text/3680-use.md https://github.com/joshtriplett/rfcs/blob/use/text/3680-use....
- dralley 1y agoIt is definitely a complex language though I would argue probably much less so, on the whole, than C++.
- meisel 1y agoIn my experience, C++ is a much more complicated language. The 8 ways to initialize something, the 5 types of values (xvalues etc.), inconsistent formatting conventions, inconsistent naming conventions, the rule of 5, exceptions, always remembering to check `this != other` when doing a move assignment operator, perfect forwarding, SFINAE, workarounds for not having a great equivalent to traits, etc. . Part of knowing the language is also knowing the conventions on top that are necessary in order to write it more safely and faster (if your move constructor is not noexcept it'll cause copies to occur when growing a vector of that object), and learning the many non-ideal competing ways that people do things, like error handling.
- GrantMoyer 1y agoThanks for organizing for me my thoughts on why even a restricted modern subset of C++ is complicated.
- jstimpfle 1y agoWhy check this != other? I've seen this once before in a codebase and concluded it was unnecessary. Asking as someone whose life became much easier after opting not do anything of the above and just write C in C++ ;-)
- tonyplee 1y agoAre there any researches/works/agents into use LLM to auto covert some/all C code to Rust? Ask LLM to generate rust code from chat, usb, i2c, GPU drivers - build and test it automatically? Possible? Or start with other "smaller" projects such as sqlite, apache, nginx, etc - possible?
- gpm 1y agoThere's non-LLM research towards doing this which has a few success stories: https://github.com/immunant/c2rust https://github.com/immunant/c2rust LLMs seem generally unsuited for the task, because they're fundamentally approximators that won't always get things right, and as a result will introduce subtle bugs. Perhaps if you paired them with some sort of formal methods... I'm not aware of anyone doing that. Tests aren't sufficient - lots of subtle bugs will not be caught by existing test suites. Your idea of "smaller" projects is not... smaller enough. See the actual success stories for example: https://github.com/immunant/c2rust?tab=readme-ov-file#uses-of-c2rust-transpile https://github.com/immunant/c2rust?tab=readme-ov-file#uses-o...
- steveklabnik 1y agoDarpa is interested in funding such an effort, but as far as I know that's the stage it's at, they haven't released any results.
- anon-3988 1y agofn project_reference(r: &MyStruct) -> &Field { &r.field } unsafe fn project_pointer(r: *mut MyStruct) -> *mut Field { unsafe { &raw mut (*r).field } } // The equivalent C code would look like this: struct field *project(struct my *r) { return &(r->field); } I am a very heavy Rust user. I mostly program in safe Rust while occassionally dipping into unsafe Rust. IDK, I think Rust should stick with what it is good at and not try to expand into domain that it is clearly not nicely designed for. That is, what if the best way to implement linked list in RUST is via an array of indices and NOT through RefCell or whatever it is? What if Rust will never ever have a sane way to implement linked list. What is so wrong with that? I think there should be a very clean divide between C and Rust. Rust stays in the happy Rust world and C stays on the happy C world. I am not sure I am excited to see something like this unsafe fn project_pointer(r: *mut MyStruct) -> *mut Field { unsafe { &raw mut (*r).field } }
- drdo 1y agoIt's not that hard to implement a linked list in Rust in exactly the same way as in C or C++, using raw pointers, and putting a safe API around it.
- piperswe 1y agoIn fact, IIRC exactly that is available in the standard library.
- lowbloodsugar 1y agoThe best way to implement a linked list is with unsafe in a collection type. You write that type once, check that it’s bullet proof, and then go onto the next thing. I’ve got a sorted map using doubly linked list and I don’t think twice about it. Using an array for a linked list means the compiler can’t tell if you are being unsafe. You still have all the same problems.
- deterministic 1y agoRust is destined to become as complicated as C++.
- Ericson2314 1y agoGah, I've been waiting for &out (and &in) for so long, a decade now. Please, Rust devs, finally give up on the idea that they aren't needed and implement them.
- surajrmal 1y agoDid you try writing an rfc proposal for them?
- Ericson2314 1y agoA wrote https://github.com/Ericson2314/rust-papers https://github.com/Ericson2314/rust-papers on that topic, and wrote RFCs on other, simpler, topics.