Rendered at 06:05:15 GMT+0000 (Coordinated Universal Time) with Wasmer Edge.
akira2501 6 days ago [-]
I personally dislike rust, but I love kernels, and so I'll always check these projects out.
This is one of the nicer ones.
It looks pretty conservative in it's use of Rust's advanced features. The code looks pretty easy to read and follow. There's actually a decent amount of comments (for rust code).
Not bad!
wg0 6 days ago [-]
Otherwise is a decent language but what makes it difficult is the borrow semantics and lifetimes. Lifetimes are more complicated to get your head around.
But then there's this Arc, Ref, Pinning and what not - how deep is that rabbit hole?
junon 6 days ago [-]
Context: I'm writing a novel kernel in Rust.
Lifetimes aren't bad, the learning curve is admittedly a bit high. Post-v1 rust significantly reduced the number of places you need them and a recent update allows you to elide them even more if memory serves.
Arc isn't any different than other languages, not sure what you're referring to by ref but a reference is just a pointer with added semantic guarantees, and Pin isn't necessary unless you're doing async (not a single Pin shows up in the kernel thus far and I can't imagine why I'd have one going forward).
mcherm 6 days ago [-]
Would you not want to use Pin when sharing memory with a driver or extension written in a different language (eg: C)?
bombela 6 days ago [-]
Pin is a pure compile time abstraction for a single problem: memory safety of self referential struct.
Pin leverages the type system to expose to the programmer receiving a pointer to a Pin'ned object, that this object has some pointer on itself (a self referencial struct). You better be mindful not to move this object to a different memory location unless you know for sure that it is safe to do so. The Pin abstraction makes it harder to forget; and easier to notice during code review; by forcing you to use the keyword unsafe for any operations on the pinned object that could move it around.
In C, there is no such way to warn the programmer besides documentation. It is up to the programmer to be very careful.
junon 5 days ago [-]
Nah not really. Pin is for self-refefential data typically. It's compile time only so that information would get lost in C anyway, and there's no way to distinguish that data at runtime.
The kernel is doing so much anyway with memory maps and flipping in / out pages for scheduling and context switching that Pin doesn't add any value in such cases anyway.
It was also specifically built for async rust. I've never personally seen it in the wild in any other context.
baq 6 days ago [-]
If you’re writing C and don’t track ownership of values, you’re in a world of hurt. Rust makes you do from day one what you could do in C but unless you have years of experience you think it isn’t necessary.
wg0 6 days ago [-]
Okay, I think it is is more like Typescript. You hate it but one day you just write small JS program and convert it to Typescript to discover that static analysis alone had so many code paths revealed that would have resulted in uncaught errors and then you always feel very uncomfortable writing plain Javascript.
But what about tools like valgrind in context of C?
rcxdude 6 days ago [-]
Valgrind can only tell you about issues that your testcases exercise. It doesn't provide the same guarantees as static checking of memory safety invariants. But, if you're really concerned (especially about unsafe code), belt-and-bracers is a good strategy, and valgrind will work with rust binaries as well. Rust also has a tool called MIRI which can similarly flag up issues in testcases (it's effectively an interpreter for the intermediate representation in the compiler, and it can detect undefined behaviour even if the compiled assembly would happen to look OK. Still has the same limitation of needing extensive testcases though)
tracker1 6 days ago [-]
A few years ago I was worrying on a Byzantine mess of a JS project. I converted everything to TS for the sole reason of somewhat safely refactoring the project as a whole.
There was so little trust in the fragility of the original, it took a few months to convince everyone the refactored TS branch was safe.
After that, feature development was a lot faster in terms of productivity again.
baq 6 days ago [-]
You probably should run your rust programs through valgrind regardless. Rust is safer than C, but any unsafe code drops you to approximately C level of safety and any C FFI calls are obviously outside of rust's control or responsibility.
badmintonbaseba 6 days ago [-]
Valgrind is great, especially if you write extensive tests and you actually run them through it regularly. And even then, it does not prove the absence of any kind of bugs. Safe rust has strong guarantees.
jimbomins 5 days ago [-]
frama-c
junon 5 days ago [-]
Which is terrible for kernel development, and is generally very hard to work with, unfortunately.
metalloid 6 days ago [-]
It was true until LLMs arrive.
Feature compilers + IDEs can be integrated with LLMs to help programmers.
Rust was a great idea, before LLMs, but I don't see the motivation for Rust when LLMs can be the solution initial for C/C++ 'problems'.
smolder 6 days ago [-]
Relying on LLMs to code for you in no way solves the safety problem of C/C++ and probably worsens it.
BrainInAJar 5 days ago [-]
probably?
even if the LLM is trained on flawless C code (which it isn't) it still has no way of reasoning about a complex system, it's just "what token is statistically most likely to come next"
smolder 5 days ago [-]
I said that because it's very possible for someone to write a more flawed program without an LLMs help. The exact probabilities weren't central to my point.
ulbu 6 days ago [-]
Rust compiler checks things for you. People trust the Rust compiler because it enforces rules they want, so people don’t have to be in its place.
Your suggestion is to be that checker to LLM-generated code. Back to square one.
baq 6 days ago [-]
On the contrary LLMs make using safe but constraining languages easier - you can just ask it how to do what you want in Rust, perhaps even by asking it to translate C-ish pseudocode.
oersted 6 days ago [-]
I don’t entirely agree, you can get used to the borrow checker relatively quickly and you mostly stop thinking about it.
What tends to make Rust complex is advanced use of traits, generics, iterators, closures, wrapper types, async, error types… You start getting these massive semi-autogenerated nested types, the syntax sugar starts generating complex logic for you in the background that you cannot see but have to keep in mind.
It’s tempting to use the advanced type system to encode and enforce complex API semantics, using Rust almost like a formal verifier / theorem prover. But things can easily become overwhelming down that rabbit hole.
jonathanstrange 6 days ago [-]
It's just overengineered. Many Rust folks don't realize it because they come from C++ and suffer from Stockholm Syndrome.
junon 5 days ago [-]
How is it overengineered?
jonathanstrange 4 days ago [-]
That's my personal opinion after I've learned it and read Klabnik's book. I'm aware that other people's mileage differs. I'm listing a few reasons below.
- Overall too complex
- Wrong philosophy: demanding the user to solve problems instead of solving problems for the user
- Trying to provide infinite backwards compatibility with crates, which leads to hidden bitrot
- Slow compilation times
- Claims to be "safe" but allows arbitrary unsafe code, and it's everywhere.
- Adding features to fix misfeatures (e.g. all that lifetime cruft; arc pointers) instead of fixing the underlying problem
- Hiding implementations with leaky abstractions (traits)
- Going at great length to avoid existing solutions so users re-invent it (e.g. OOP with inheritance; GC), or worse, invent more complex paradigms to work around the lack (e.g. some Rust GUI efforts; all those smart pointer types to work around the lack of GC)
- A horrendous convoluted syntax that encourages bad programming style: lot's of unwrap, and_then, etc. that makes programs hard to read and audit.
- Rust's safe code is not safe: "Rust’s safety guarantees do not include a guarantee that destructors will always run. [...] Thus, allowing mem::forget from safe code does not fundamentally change Rust’s safety guarantees."
It already has similar complexity and cognitive demands as C++ and it's going to get worse. IMHO, that's also why it's popular. Programmers love shitty languages that allow them to show off. Boring is good.
j-krieger 15 hours ago [-]
> Claims to be "safe" but allows arbitrary unsafe code, and it's everywhere.
Sigh. This is not true. Not the first part, and especially not the last part.
`Unsafe` doesn't allow arbitrary, unsafe code. It resets the compiler to a level where most manually managed languages are all the time. You still have to uphold all guarantees the compiler provides, just manually. That's why Miri exists.
jonathanstrange 8 hours ago [-]
Either it's safe or it's unsafe. If you use the keyword "unsafe" it should definitely not mean "safe" (and it doesn't, but you seem to suggest it).
8 hours ago [-]
junon 3 days ago [-]
> Overall too complex
Completely subjective. I've learned all there is to learn about Rust's syntax and most of its standard libraries, I think, and it's really not all that, in my personal opinion. There are certainly much more complex languages out there, even dynamic languages. I'd argue Typescript is more complex than Rust as a language.
> Wrong philosophy: demanding the user to solve problems instead of solving problems for the user
I have no idea what you mean by this. Do you mean you want more magic?
> Trying to provide infinite backwards compatibility with crates, which leads to hidden bitrot
Backwards compatibility reduces bitrot. Bitrot is when the ecosystem has moved on to a point of not supporting features used by stale code, thus making the code partially or completely unusable in newer environments as time progresses and the code doesn't update.
The Rust editions explicitly and definitively solve the bitrot problem, so I'm not sure what you're on about here.
> Slow compilation times
Sure, of course. That's really the biggest complaint most people have, though I've had C++ programs take just as long. Really depends on how the code is structured.
> Claims to be "safe" but allows arbitrary unsafe code, and it's everywhere.
Unsafe isn't a license to kill. It also doesn't allow "arbitrary" code. I suggest reading the rustnomicon, the book about Rust undefined behavior. All `unsafe` code must adhere to the postcondition that no undefined behavior is present. It also doesn't remove borrow checking and the like. Without `unsafe` you couldn't do really anything that a systems language would need to do in certain cases - e.g. writing a kernel requires doing inherently unsafe things (e.g. switching out CR3) where no compiler on earth currently written will understand those semantics.
People seem to parrot this same "unsafe nullifies rust's safety" without really understanding it. I suppose they could have renamed the `unsafe` keyword `code_the_does_stuff_unverifiable_by_the_compiler_so_must_still_adhere_to_well_formed_postrequisites_at_risk_of_invoking_undefined_behavior` but alas I think it'd be pretty annoying to write that so often.
It's pretty typical to abstract away `unsafe` code into a safe API, as most crates do.
> Adding features to fix misfeatures (e.g. all that lifetime cruft; arc pointers) instead of fixing the underlying problem
Lifetimes aren't "cruft", not sure what you mean. They've also been elided in a ton of cases.
An "arc pointer" isn't a thing; there's ARC (which is present in every unmanaged language, including C++, Objective-C, Swift, etc). I'm not sure what the "underlying problem" is you're referring to. Rust takes the position that the standard library shouldn't automatically make e.g. Mutexes an atomically reference counted abstraction, but instead allow the user to determine if reference counting if even necessary (Rc<Mutex>) and if it should be atomic so as to be shareable across cores (Arc<Mutex>). This type composure is exactly why Rust's type system is so easy to work with, refactor and optimize.
> Hiding implementations with leaky abstractions (traits)
Sorry for being blunt but this is a word salad. Traits aren't leaky abstractions. In my personal experience they compose so, so much better and have better optimization strategies than more rigid OOP class hierarchies. So I'm not sure what you mean here.
> Going at great length to avoid existing solutions so users re-invent it (e.g. OOP with inheritance; GC), or worse, invent more complex paradigms to work around the lack (e.g. some Rust GUI efforts; all those smart pointer types to work around the lack of GC)
Trait theory has been around for ages. GC is not a silver bullet and I wish people would stop pretending it was. There are endless drawbacks to GC. "All those smart pointer types" -- which ones? You just seem to want GC. I'm not sure why you want GC. GC solves few problems and creates many more. It can't be used in a ton of environments, either.
> A horrendous convoluted syntax that encourages bad programming style: lot's of unwrap, and_then, etc. that makes programs hard to read and audit.
This is completely subjective. And no, there's not a lot of `and_then`, I don't think you've read much Rust. Sorry if I'm sounding rude, but it's clear to me by this point in my response that you've played with the language only at a very surface level and have come to some pretty strong (and wrong) conclusions about it.
If you don't like it, fine, but don't try to assert it as being a bad language and imply something about the people that use it or work on it.
> Rust's safe code is not safe: "Rust’s safety guarantees do not include a guarantee that destructors will always run. [...] Thus, allowing mem::forget from safe code does not fundamentally change Rust’s safety guarantees."
You misunderstand what it's saying there but I'm honestly tired of rehashing stuff that's very easily researched that you seem to not be willing to do.
jonathanstrange 3 days ago [-]
That's a lengthy and passionate reply. The phrases "in my opinion" and "other people's mileage may differ" should have given away that my take was mostly subjective opinion. Rust is definitely not a language for me and would be a bad choice for the projects I'm working on. I continue to think it's totally overengineered. But, as noted before, other people's mileage may differ.
As long as the Rust fans stick to their favorite language, everybody can be happy.
KingOfCoders 6 days ago [-]
I always feel Arc is the admission that the borrow checker with different/overlapping lifetimes is too difficult, despite what many Rust developers - who liberally use Arc - claim.
jeroenhd 6 days ago [-]
Lifetime tracking and ownership are very difficult. That's why languages like C and C++ don't do it. It's also why those languages needs tons of extra validation steps and analysis tools to prevent bugs.
Arc is nothing more than reference counting. C++ can do that too, and I'm sure there are C libraries for it. That's not an admission of anything, it's actually solving the problem rather than ignoring it and hoping it doesn't crash your program in fun and unexpected ways.
Using Arc also comes with a performance hit because validation needs to be done at runtime. You can go back to the faster C/C++ style data exchange by wrapping your code in unsafe {} blocks, though, but the risks of memory corruption, concurrent access, and using deallocated memory are on you if you do it, and those are generally the whole reason people pick Rust over C++ in the first place.
GoblinSlayer 6 days ago [-]
Looking at the code, it consists of long chains of get().unwrap().to_mut().unwrap().get() noise. Looks like coping with library design than ownership tacking. Also why Result<Option<T>>? Isn't Result already Option by itself? I guess that's why you need get().unwrap().to_mut() to get a value from Result<Option<T>> from an average function call?
thesuperbigfrog 6 days ago [-]
>> Also why Result<Option<T>>? Isn't Result already Option by itself?
No. I've written code that returns Result<Option<T>>. It was a wrapper for a server's query web API.
The Result part determines whether the request succeeded and the response is valid.
The Option part is because the parameter being queried might not exist. For example, if I ask the API for the current state of the user session with a given Session ID, but that Session ID does not exist, then the Rust wrapper could return OK(None) meaning that the request succeeded, but that no such session was found.
oniony 6 days ago [-]
Result is whether an operation returned an error or not. Option is whether you have a value or no value.
thesuperbigfrog 6 days ago [-]
Exactly.
That is why a query that successfully returns no items can be represented as Ok(None).
A successful query with items returned would instead be Ok(Vec<Item>).
An error in the completing the query (for example, problem with the database), would be Err(DatabaseError) or Err(SomeOtherError).
GoblinSlayer 6 days ago [-]
Presumably missing session is an alternative scenario and thus should be reported as an error, then you match and handle this error. Your design complicates the common scenario: in case of valid session you need double unwrap, cf File::open that could return Result<Option<File>> if file is not found.
thesuperbigfrog 6 days ago [-]
>> Presumably missing session is an alternative scenario and thus should be reported as an error
But in this case, a query using an invalid session ID is not an error. It is asking for details about something that does not exist.
>> cf File::open that could return Result<Option<File>> if file is not found.
This type of query is not like File::open which gets a handle to a resource. Trying to get a handle to a resource that does not exist is an error.
This type of query is read-only and does not allocate any resources or prepare to do anything with the session.
It simplifies the control flow because it distinguishes between errors in completing a query versus the presence or absence of items returned from the query.
lenkite 5 days ago [-]
How does the caller know whether the response was empty because of an invalid session id ? You have conflated empty response with an erroneous situation. The simplest solution is just Result<T, E>.
thesuperbigfrog 5 days ago [-]
>> How does the caller know whether the response was empty because of an invalid session id ?
Documentation and how SQL database queries work.
The documentation states that a valid session id will return a SessionInfo struct (since it is an Option the type is Some(SessionInfo) ), and that an invalid session id will return None.
If the SQL query is something like "SELECT * FROM USER_SESSIONS WHERE USER_SESSION_ID = $1" then if an invalid session id is provided the database returns zero rows. The query was successful, but there were no matching sessions with that session id.
>> You have conflated empty response with an erroneous situation. The simplest solution is just Result<T, E>.
Again, an empty response is not an error in this situation. If your database query returns zero rows, is it an error? The database query succeeded. There are no sessions with the provided session id. What error occurred?
LinXitoW 6 days ago [-]
If I ask my repository (backed by an sql db) to get a user, there might be 3 different scenarios I'm interested in:
- Technical problem (like connection problems) means I don't know what's in the db
- No technical problem, but no user entry
- No technical problem, and a user entry
You need the Result for the technical problems, and the Option for whether there's a user entry or not.
GoblinSlayer 6 days ago [-]
Surely Result is supposed to hold both system errors and business errors.
Galanwe 6 days ago [-]
It's not that the borrow checker is too difficult, it's that it's too limiting.
The _static_ borrow checker can only check what is _statically_ verifiable, which is but a subset of valid programs. There are few things more frustrating than doing something you know is correct, but that you cannot express in your language.
acomar 6 days ago [-]
I've found the opposite. every time I attempt to subvert the borrow checker, I eventually discover that I'm attempting to write a bug.
netbsdusers 6 days ago [-]
For kernels (and I suspect database engines might be added to the list, since they seem to have similar requirements to be both scalable and deal with massive amounts of shared state, but I'm not overly familiar with them) is where it gets particularly difficult.
Several kernels for example use type-stable memory, memory that is guaranteed to only hold objects of a particular type, though perhaps only providing that guarantee for as long as you hold an RCU read-lock (this is the case in Linux with SLAB_TYPESAFE_BY_RCU). It is possible in some cases to be able to safely deal with references to objects where the "lifetime" of the referent has ended, but where by dint of it being guaranteed to be the same type of object, you can still do what you want to do.
This comes in handy when you have a problem that commonly appears in kernels where you need to invert a typical lock ordering (a classic case is that the page fault codepath might want to lock, say, VM object then page queue, but the page-replacement codepath will want to lock page-queue then VM object.)
Unfortunately it's hard to think of how the preconditions for these tricks could be formally expressed.
andrewflnr 6 days ago [-]
Wouldn't you want the relevant Rust lifetime to be that of the type-stable memory block, not the individual "object" inside? I'm not that familiar with kernel programming, but that sounds a lot like an arena, and (IIRC) that's the approach with an arena.
GolDDranks 6 days ago [-]
It's not just difficult, sometimes it's impossible to statically know a lifetime of a value, so you must dynamically track it. Arc is one of such tools.
lmm 6 days ago [-]
If tracking lifetimes is simple 90% of the time and complex 10% of the time, maybe a tool that lets you have them automatically managed (with some runtime overhead) that 10% of the time is the right way forward.
tracker1 6 days ago [-]
Then you can use a language and runtime like C# or Java. Or you can use patterns like Go promotes.
There are lots of options if you want.
lmm 5 days ago [-]
> Then you can use a language and runtime like C# or Java. Or you can use patterns like Go promotes.
But in that case you're stuck paying the overhead 100% of the time, even though 90% of the lifetimes are simple. (Perhaps a little less so with escape analysis etc., but doing it at compile time in a way that's understandable in the source feels a lot more reliable)
neonsunset 5 days ago [-]
Java and C# are languages of different class. C# is perfectly capable of systems programming and manual memory management that is at least more convenient than C (but not C++ with move semantics and operator overloading abuse, otoh C#'s type system and build process are saner which at least partially pays for this).
surajrmal 6 days ago [-]
Arc usually means you've not structured your code to have clear lifetimes where one object clearly outlives another. Typically I see c++ applications avoid it but actually suffer from bugs due to the same structural deficiencies. They said, I think it's almost always possible to to avoid it if you try hard enough. With async you need to use structured concurrency.
oneshtein 6 days ago [-]
Rust lifetime is just a label for a region of memory with various data, which is discarded at the end of its life time. When compiler enters a function, it creates a memory block to hold data of all variables in the function, and then discards this block at the exit from the function, so these variables are valid for life time of the function call only.
IshKebab 6 days ago [-]
Rust code is usually well commented in my experience.
cies 6 days ago [-]
Instead of asking "what other languages and project (open/closed, big/small, web/mobile/desktop, game/consumerapp/bizapp) have you experience with as to come to this conclusion?" people down vote you.
So lemme ask: what other languages and project (open/closed, big/small, web/mobile/desktop, game/consumerapp/bizapp) have you experience with as to come to this conclusion?
dangsux 6 days ago [-]
[dead]
ramon156 6 days ago [-]
I expect the downvotes to be there because it's talking positively about rust, which is blasphemy! /j
tracker1 6 days ago [-]
I'm guessing a lot of any perception of a lack of comments or documentation in a rust codebase comes down to how new or green a developer is to rust.
If you're just starting out or doing something relatively simple, your goal is to get something working. This is so true regardless of the language.
jimbomins 5 days ago [-]
I've never looked at any Rust. But this mini thread leaves me expecting the Rust world to be like Perl. The experienced Rust/Perl user uses every feature and short cut for magnificently dense expressive (alt. incomprehensible gibberish to anyone else) and doesn't comment it because the code is self evident. When actually they just want to code wank showing how clever they are and how lazy anyone else is if they haven't take the time to understand the details and thus understand.
But like I said, I've not looked at any Rust despite its marketing success.
tracker1 3 days ago [-]
I've read a lot more Rust than I've written at this point... A lot of what I've seen has been really easy to reason with and follow. There are a few features that are a bit harder to grok, especially with complex access lifetimes. Generally those complexities have been more from the inexperienced as a lot of what I've seen from more experienced devs simplifies those complex points of interaction making the entirety more easy to reason with.
I find a lot of the complexities tend to come from devs with more experience in communities that tend to add complexity by nature (C# and Java devs in particular). YMMV of course, that's just been my take so far. I've written a few simple web (micro)services in Rust and a couple of playground Tauri apps. I will say the simpler tasks have been incredibly easy to work through.
Though I may not have always taken the absolutely most performant, least memory path of work, it's been smaller/faster than other platforms and languages I have more experience with. And that's without even getting into build/compile time optimization options.
iknowstuff 6 days ago [-]
for the downvoters: it’s true, and it’s because of rustdoc and doctests. comments become publicly browsable documentation, and any code contained within is run as a part of the test suite.
cgh 5 days ago [-]
Javadoc pioneered this 25+ years ago and despite that, there's plenty of poorly-documented Java code out there. Orders of magnitude more of it than all of the Rust code in existence, in fact.
Intuition tells me that Rust is young enough to attract a certain type of early adopter, the kind of programmer who is more likely to document their code well from the outset.
1oooqooq 6 days ago [-]
think the downvotes are because of relevance. point was not using advanced rust features, not being documented
forks 6 days ago [-]
I don't see how the relevance is in question. GGGP said "There's actually a decent amount of comments (for rust code)." GGP seems to be responding to that parenthetical.
justmarc 6 days ago [-]
I'm interested in these kind of kernels to run very high performance network/IO specific services on bare metal, with minimal system complexity/overheads and hopefully better (potential) stability and security.
The big concern I have however is hardware support, specifically networking hardware.
I think a very interesting approach would be to boot the machine with a FreeBSD or Linux kernel, just for the purposes of hardware as well as network support, and use a sort of Rust OS/abstraction layer for the rest, bypassing or simply not using the originally booted kernel for all user land specific stuff.
nijave 6 days ago [-]
Couldn't you just boot the Linux kernel directly and launch a generic app as pid 1 instead of a full blown init system with a bunch of daemons?
That's basically what you're getting with Docker containers and a shared kernel. AWS Lambda is doing something similar with dedicated kernels with Firecracker VMs
mjevans 6 days ago [-]
Yes, you can. You can even have a different Pid 1 configure whatever and then replace it's core image with the new Pid 1.
justmarc 6 days ago [-]
Yes, but I wanted to bypass having the complexity of the Linux kernel completely, too.
Basically single app directly to network (the world) and as little as possible else in between.
afr0ck 6 days ago [-]
Linux kernel is not complex. Most of the code runs lock-free. For example, the slab allocator in the kernel uses only a single double_cmpxhg instruction to allocate an object via kmalloc(). The algorithm scales to any number of CPUs and has NUMA awareness. Basically, the most concurrent, lowest allocation latency allocator you can get in the market, which also returns the best objects for the requesting process on big memory systems.
The complexity on the other hand is architectural and logical to achieve scale to hundreds of CPUs, maximise bandwidth and reduce latency as much as possible.
Any normal Rust kernel will either have issues scaling on multi-cores or use tax-heavy synchronisation primitives. The kernel RCU and lock-free algorithm took a long time to be discovered and become mature and optimised aggressively to cater for the complex modern computer architectures of out-of-order execution, pipelining, complex memory hierarchies (especially when it comes to caching) and NUMA.
ladyanita22 4 days ago [-]
> Any normal Rust kernel will either have issues scaling on multi-cores or use tax-heavy synchronisation primitives. The kernel RCU and lock-free algorithm took a long time to be discovered and become mature and optimised aggressively to cater for the complex modern computer architectures of out-of-order execution, pipelining, complex memory hierarchies (especially when it comes to caching) and NUMA.
Why would that be the case at all? What has Rust anything to do with that?
sshine 5 days ago [-]
A new kernel can never beat legacy kernels on hardware support.
To reach a useful state, you only need to be highly performant on a handful of currently popular server architectures.
> Any normal Rust kernel will either have issues scaling on multi-cores or use tax-heavy synchronisation primitives.
I'm not sure how that applies to Asterinas. Is Asterinas any normal Rust kernel?
If you want truly high-performance networking, you can bypass the kernel altogether with DPDK. So you don't have to worry about alternative kernels for other tasks at all. On the downside, DPDK takes over the NIC entirely, removing the kernel from the equation, so if you need the kernel to see network traffic for some reason, it won't work for you.
Their conclusion is io_uring is still slower but not by much, and future improvements may make the difference negligible. So you're right, at least in part. Given the tradeoffs, DPDK may not be worth it anymore.
loeg 6 days ago [-]
There are also just a bunch of operational hassles with using DPDK or SPDK. Your usual administrative commands don't work. Other operations aren't intermediated by the kernel -- instead you need 100% dedicated application devices. Device counters usually tracked by the kernel aren't. Etc. It can be fine, but if io_uring doesn't add too much overhead, it's a lot more convenient.
guenthert 6 days ago [-]
"io_uring had a maximum throughput of 5.0 Gbit/s "
Wut? More than 10 years ago, a cheap beige box could saturated a 1Gbps link with a kernel as it came from e.g. Debian w/o special tuning. A somewhat more expensive box could get a good share of a 10Gbps link (using Jumbo frames), so these new results are, er, somewhat underwhelming.
rcxdude 6 days ago [-]
Packet size does affect the throughput quite a lot, though. The tests in the paper are without jumbo frames (I do agree though, that the results in that paper can't really be described as 'close', when io_uring is 1/5 the speed, only achieves that at the largest packet size, and has much more packet loss under those conditions)
renox 6 days ago [-]
Not by much?? You're exaggerating..
guenthert 6 days ago [-]
That's an interesting and valuable study. I was slightly disappointed though that only a single host was used in the 'network' performance tests:
"SR-IOV was used on the NIC to enable the use of virtual functions, as it was the only NIC that was available during the study for testing and therefore the use of virtual functions was a necessity for conducting the experiments."
monocasa 6 days ago [-]
I'm not sure that's true for a good chunk of the workloads that dpdk really shines on.
A lot of the benefit of dpdk is colocating your data and network stack in the same virtual memory context. io_uring I can see getting you there if you have you're serving fixed files as a cdn kind of like netflix's appliances, but for cases where you're actually doing branchy work on the individual requests, dpdk is probably a little easier to scale up to the faster network cards.
GoblinSlayer 6 days ago [-]
If you use io_uring, you're subject to vulnerabilities in kernel network stack which you have no control over.
not_a_dane 6 days ago [-]
that's rare.
treeshateorcs 6 days ago [-]
i might be wrong but if it's ABI compatible the same drivers will work?
p.s.: i was wrong
>While we prioritize compatibility, it is important to note that Asterinas does not, nor will it in the future, support the loading of Linux kernel modules.
Linux doesn't even maintain ABI compatibility with itself, nobody else is going to manage it. The possibility that might work is there's a couple projects that maintain just enough API compatibility to reuse driver code from Linux (IIRC FreeBSD does this for some graphics drivers). But even then you're gambling with whether Linux decides to change implementation details one day, since internal APIs explicitly aren't stable.
bcrl 6 days ago [-]
The Linux kernel community takes ABI compatibility for userland very seriously. That developers in userland are frequently unwilling to understand issues surrounding ABI stability is not the fault of the Linux kernel.
yjftsjthsd-h 6 days ago [-]
Oh sure, the user-space ABI is stable; I meant kernel-space. Although I realize now that I failed to write that explicitly.
bcrl 6 days ago [-]
The past 30 years of the Linux kernel's evolution has proven that there is no need for a stable kernel ABI. That would make refactoring, adding new features and porting to new platforms exceedingly difficult. Pretty much all of the proprietary kernel modules have either become open source or been replaced by open source replacements. The Linux community doesn't need closed source kernel modules for VMWare anymore, and even Nvidia has finally given up on their closed source GPU drivers. Proprietary Linux kernel modules have no place in the modern world.
vlovich123 6 days ago [-]
> even Nvidia has finally given up on their closed source GPU drivers.
lol. No. They just added a CPU and then offloaded all the closed source userspace driver code to it leaving behind the same dumb open sourceable kernel driver shim as before (ie instead of talking to userspace it talks to the GPU’s CPU).
> The past 30 years of the Linux kernel's evolution has proven that there is no need for a stable kernel ABI.
What the last 30 years have shown is that there is actually a need for it, otherwise DKMS wouldn’t be a thing. Heck, intel’s performance profiler can’t keep up with the kernel changes which means you get to pick running an up to date kernel or be able to use the open source out-of-tree kernel module. The fact that Linux is alone in this should make it clear it’s wrong. Heck Android even wrote their own HAL to try to make it possible to update the kernel on older devices. It’s an economics problem that the Linux kernel gets to pretend doesn’t exist but it’s a bad philosophical position. It’s possible to support refactoring and porting to new platforms while providing ABI compatibility and Linux is way past the point where it would even be a minor inconvenience - all the code has ossified quite a bit anyway.
lmm 6 days ago [-]
> The past 30 years of the Linux kernel's evolution has proven that there is no need for a stable kernel ABI.
My experience of using Linux and having devices that used to work become unsupported suggests just the opposite.
GoblinSlayer 6 days ago [-]
It depends on your goals, but at least Torvalds believes driver availability is important and unstable ABI is known to hinder driver availability.
> While we prioritize compatibility, it is important to note that Asterinas does not,
nor will it in the future, support the loading of Linux kernel modules.
justmarc 6 days ago [-]
It's a lot "simpler" to support a Linux userland as that means one needs to "just" emulate all the Linux syscalls, than to implement the literally countless internal APIs needed for drivers etc, as that would otherwise mean literally reimplementing the whole Linux kernel and that's neither realistic, nor too useful.
mgerdts 6 days ago [-]
And that’s not all that simple, as has been experienced by Solaris (never released(?) Linux branded zones, illumos (lx brand), and Windows (WSL1) developers that have tried to make existing kernels act like Linux.
It’s probably easier if the kernel’s key goal is to be compatible with the Linux ABI rather than being compatible with its earlier self while bolting on Linux compatibility.
yjftsjthsd-h 5 days ago [-]
I'm sure it's not trivial, but I was under the impression that illumos, FreeBSD, and NetBSD all have perfectly good Linux compatibility layers so it's clearly doable. (WSL1 excepted because NT apparently really doesn't want to be a unix-like)
mgerdts 4 days ago [-]
From my experience working on it from time to time at Joyent, the parts that are implemented work pretty well on the lx brand in illumos. At the time, things like cgroups and namespaces were not implemented and there was no clear path to implement them. It’s kinda hard to participate in the docker or k8s ecosystem with such limitations.
I was hired at Joyent largely to work on bhyve so that Triton and Joyent’s public cloud had a way to run Linux VMs when full Linux compatibility was more important than the efficiency of zones/containers.
Jyaif 6 days ago [-]
> emulate all the Linux syscalls
and emulate the virtual filesystems (/proc/...)
justmarc 6 days ago [-]
No, it means you can run Linux userland/apps on this kernel, to the level/depth which they currently support of course.
They might not yet implement everything that's needed to boot a standard Linux userland but you could say boot straight into a web server built for Linux, instead of booting into init for example.
dathinab 6 days ago [-]
in general the ABI is kernel<->user space while the ABI (and potentially even API) on the inside (i.e. for drivers) can change with every kernel version (part of why it's so important to maintain drivers in-tree)
protoman3000 6 days ago [-]
Why don’t you just use a SmartNIC and P4? It won’t get faster than running on the NIC itself
tiffanyh 6 days ago [-]
OT: if you're interested in Asterinas, you might also be interested in Redox (entire OS written in Rust).
I love Redox as a project because while it still has a massive ways to go, it's the closest to being a new OS/Kernel that has the potential to make it to a viable daily driver. Windows/MacOS/Unix/Linux are all incredibly old by software standards and Redox is bringing some cool design decisions.
metaketa 6 days ago [-]
This is fascinating! Couldn't really find the kernel code but would love to know more about the applicability. I'm curious since seeing the Unikraft release that promised millisecond container boot times
Redox has a proper architecture, aka microkernel multiserver.
Thus it is a much more interesting project.
apatheticonion 4 days ago [-]
To be fair Aester is just a monolithic kernel that philosophically quarantines unsafe code to the lowest level of the kernel.
You still have kernel modules for microkernel-like functionality
exabrial 6 days ago [-]
I think this looks incredible. Like how does one create a compatible abi _for all of linux_??? Wow!
> utilize the more productive Rust programming language
Nitpick: it’s 2024 and these ‘more productive’ comparisons are silly, completely unscientific, And a bit of a red flag for your project: The most productive language for a developer is the one they understand what is happening one layer below the level of abstraction they are working with. Unless you’re comparing something rating Ruby vs RiscV assembly, it’s just hocus-pocus.
jmmv 6 days ago [-]
> I think this looks incredible. Like how does one create a compatible abi _for all of linux_??? Wow!
It’s hard to get _everything_ perfectly right but not that difficult to get most of it working.
NewJazz 6 days ago [-]
IIRC Fuschia has something similar. And maybe Redox?
dathinab 6 days ago [-]
Idk. Asahi Linux GPU driver breaks all "common sense" of "how fast a reliable usable feature rich driver" was produced by a small 3rd party team.
The company I work for has both rust and python projects (through partially pre "reasonable python type linting" using mypy and co.) and the general consensus there is "overall" rust is noticeable more productive (and stable in usage/reliable), especially if you have code which changes a lot.
A company I worked previous for had used rust in the very early days (around 1.0 days) and had one of this "let's throw up a huge prototype code base in a matter of days and then rewrite it later" (basically 90% of code had huge tech dept). But that code base stuck around way longer then intended, caused way less issues then expected. I had to maintain it a bit and in my experience with similar code in Python and Js (and a bit Jave) I expected it to be very painful but surprisingly it wasn't, like at all.
Similar comparing my experience massive time wastes due to having to debug soundness/UB issues in Rust, with experiences in C/C++ it's again way more productive.
So as long as you don't do bad stuff like over obsessing with the type system everything in my experience tells me using Rust is more productive (for many tasks, definitely not all task, there are some really grate frameworks doing a ton of work for you in some languages against which the rust ecosystem atm. can't compete).
---
> Most productive language for a developer is the one they understand what is happening one layer below the level of abstraction they are working with.
I strongly disagree, the most productive language is the one where the developer doesn't have to care much about what happens in a layer below in most cases. At least as long as you don't want obsess over micro optimizations not being worth the time and opportunity cost they come with for most companies/use cases.
kelnos 6 days ago [-]
> Like how does one create a compatible abi _for all of linux_???
You look at Linux's syscall table[0], read through the documentation to figure out the arguments, data types, flags, return values, etc., and then implement that in your kernel. The Linux ABI is just its "library" interface to userspace.
It's probably not that difficult; writing the rest of the kernel itself is more challenging, and, frankly, more interesting. Certainly matching behavior and semantics can be tricky sometimes, I'm sure. And I wouldn't be surprised if the initial implementation of some things (like io_uring, for example, if it's even supported yet) might be primitive and poorly optimized, or might even use other syscalls to do their work.
But it's doable. While Linux's internal ABI is unstable, the syscall interface is sacred. One of Torvalds' golden rules is you don't break userspace.
> You look at Linux's syscall table[0], read through the documentation to figure out the arguments, data types, flags, return values, etc., and then implement that in your kernel.
As well as some subset of the files expected in /dev, /proc, /sys, and similar, which are also part of the userspace ABI. And the startup mechanisms for processes, and the layout of AUXV...
It's absolutely doable, but the interface is wider than just the syscall layer.
ozgrakkurt 6 days ago [-]
Everyone says what they are used to is better or more productive. Even in assembly vs ruby, some stuff are much easier in assembly and maybe impossible in ruby afaik
exabrial 6 days ago [-]
I’m aging myself, but ~17 years ago I was in San Diego for a conference. There was a table level competition to see who could write the fastest program in 20 minutes (we were doing a full text search of a ‘giant’ 5g file). One of the guys at the table wrote some SPARC assembly to optimize character matching that was a hotspot like he was speaking French.
Ah good times.
pjmlp 6 days ago [-]
Besides all examples, Microsoft is now using TockOS for Pluton firmware, another Rust based OS.
Exactly. I see elsewhere in this page people comparing this project to Linus Torvalds starting an OS in his dorm room while studying CS. Like these were "young and clueless" devs writing an OS for fun.
From the looks of it, this seems like a serious corporate backed project made by employees of the Ant Group, the chinese fintech giant. A more fair comparison would be with Google's Fuchsia OS (defunct) or Huawei's HarmonyOS. It may succeed, it may fail, but it's nothing like a couple of kids doing a passion project to learn Rust.
> In the framekernel OS architecture, the entire OS resides in the same address space (like a monolithic kernel) and is required to be written in Rust. However, there's a twist---the kernel is partitioned in two halves ... the unprivileged Services must be written exclusively in safe Rust.
Unprivileged services can exploit known compiler bugs and do anything they want in safe Rust. How this affects their security model?
rcxdude 6 days ago [-]
I think it's not so much intended as a "you can allow arbitrary untrusted code to run as an unprivileged service" and more "a buggy unprivileged service won't compromise the whole system".
Klasiaster 6 days ago [-]
There was also the similar project Kerla¹ but development stalled. Recently people argued that instead of focusing on Rust-for-Linux it would be easier to create a drop-in replacement like these two. I wonder if there are enough people interested to make this happen as a sustained project.
> Recently people argued that instead of focusing on Rust-for-Linux it would be easier to create a drop-in replacement like these two
I guess it depends on what they mean by "easy". Certainly it's easier in the sense that you can just write code all day long, and not have to deal with the politics about Rust inside Linux, or deal with all the existing C interfaces, finding ways to wrap them in Rust in good, useful ways that leverage Rust's strengths but don't make it harder to evolve those C interfaces without trouble on the Rust side.
But the bulk of Linux is device drivers. You can build a kernel in Rust (like Asterinas) that can run all of a regular Linux userland without recompilation, and I imagine it's maybe not even that difficult to do so. But Asterinas only runs on x86_64 VMs right now, and won't run on real hardware. Getting to the point where it could -- especially on modern hardware -- might take years. Supporting all the architectures and various bits of hardware that Linux supports could take decades. I suppose limiting themselves to three or four architectures, and only supporting hardware made more recently could cut that down. But still, it's a daunting project.
depressedpanda 6 days ago [-]
From the README:
> Currently, Asterinas only supports x86-64 VMs. However, our aim for 2024 is to make Asterinas production-ready on x86-64 VMs.
I'm confused.
wrs 6 days ago [-]
I think it’s “Currently, Asterinas only supports x86-64 VMs. However, [rather than working on additional architectures this year,] our aim for 2024 is to make Asterinas production-ready on x86-64 VMs.”
favorited 6 days ago [-]
Sounds like their goal is to improve their x86-64 support before implementing other ISAs.
nurb 6 days ago [-]
It's clearer from the book roadmap:
> By 2024, we aim to achieve production-ready status for VM environments on x86-64.
> In 2025 and beyond, we will expand our support for CPU architectures and hardware devices.
They lack essential things for a kernel that could be used in production, viz. not kernel panicing during out-of-memory conditions, not an easy thing to retrofit when you have designed without consideration of it. It will probably take a bit more than 2 and a half months to rectify that.
They've been working on it for a while so they can get rust into the linux kernel
None4U 6 days ago [-]
Distinction here is between "supports" and "production-ready on", not "x86-64" and "x86-64"
convolvatron 6 days ago [-]
it would be nice to know how much userspace it supports. supporting the dynamic loader, reasonable futexes, epoll, signals, uring are all big milestones
There's also tons of ioctls and /proc and what not.
phlip9 6 days ago [-]
Super cool project. Looks like the short-term target use-case is running a Linux-compatible OS in an Intel TDX guest VM with a significantly safer and smaller TCB. Makes sense. This way you also postpone a lot of the HW driver development drudgery and instead only target VM devices.
spease 6 days ago [-]
What’s the intended use case for this? Backend containers?
Animats 6 days ago [-]
Makes a lot of sense for virtual machine containers. Inside a container inside a VM, you need far less operating system.
wg0 6 days ago [-]
Side question - I have always wondered how a Linux system is configured at the lowest level?
Let's take example of network. There's IP address, gateway, DNS, routes etc. Depending on distribution we might see something like netplan reading config files and then calling ABI functions?
Or Linux kernel directly also reads some config files? Probably not...
NewJazz 6 days ago [-]
Linux kernel as much as possible tries not to parse or read external data (besides stuff like acpi tables, device trees, hardware registers). For networking, you might look at the iproute codebase to see how they do things like bring a network device up, or create a bridge device, add a route, et cetera.
Edit: looks like iproute2 uses NETLINK, but non-networking tools might use syscalls or device ioctls.
It's just what we used to call a "layered architecture".
wiz21c 6 days ago [-]
> Linux-compatible ABI
Does it mean it can re-use the drivers written for hardware to run with linux ?
eptcyka 6 days ago [-]
No. The drivers in Linux are kernel modules, most often in-tree - meaning that the source for the drivers is built along the rest of the kernel source code. Most hardware drivers depend on various common kernel structures that change often - when they do, the source for drivers is fixed practically in the same git branch. There is no driver ABI to speak of.
dezgeg 6 days ago [-]
No. There is no stable ABI nor API for in-kernel device drivers.
apatheticonion 4 days ago [-]
Do other mainstream kernels have a stable driver API?
I guess the NT kernel needs to. Does Darwin?
hulitu 4 days ago [-]
> Asterinas: OS kernel written in Rust and providing Linux-compatible ABI
> Currently, Asterinas only supports x86-64 VMs.
So no real hardware.
apatheticonion 4 days ago [-]
I wish I could work on this as my paid day job.
As soon as I can financially retire, I'll make contributing to this my full time job!
6 days ago [-]
delduca 6 days ago [-]
This is exactly what I was discussing with a friend who works on the kernel. I don’t think Rust should be supported; the kernel should remain in C. Instead, a completely new kernel in Rust should be created with API/ABI compatibility with the original kernel.
apatheticonion 4 days ago [-]
Shame about the lack of a stable kernel driver ABI/API in Linux otherwise this kernel could inherent a lot of drivers.
xiaodai 6 days ago [-]
Lol. I am Malaysian Chinese but I honestly don't think anyone will put into production a Chinese made kernel. The risk is too high, same as no one will use a Linux distro coming out of Russian, Iran or NK. It's just cultural bias in the west.
edelbitter 5 days ago [-]
Its not the Chinese words that scare me.
It the English "safety" and "security" referring to specific properties and concepts... but wildly different ones between sentences. Like its all 2009 again and we are hoping we avoided XSS when we picked the appropriate quote/encode/escape method.
gpm 6 days ago [-]
Supposing it caught on... which do you think is riskier? Running an OS written in mostly memory safe code that somewhat might have tried to slip a backdoor in, or running an OS written in mostly memory unsafe code that has a long history of vulnerabilities and the Chinese almost certainly know about a vulnerability in.
If this catches on and has generally been subject to significant third party code review with positive results, I'm not sure any backdoor is lower cost to use than an equivalent linux vulnerability. To be fair, I'm not sure it isn't either.
throw4950sh06 6 days ago [-]
You're wrong. A lot of Chinese code and hardware is in production in the west. Huawei networking hardware is widespread, for example.
tredre3 6 days ago [-]
> Huawei networking hardware is widespread
That's an interesting example because Huawei equipment is currently being removed by several Western countries (UK, Canada, US, Germany) specifically because it's Chinese.
When we got a license for a private LTE network in the middle of the Greenland ice sheet, the one stipulation was we couldn't use Huawei equipment...
jackhalford 6 days ago [-]
The building process happens in a container?
> If everything goes well, Asterinas is now up and running inside a VM.
Seems like the developers are very confident about it too
6 days ago [-]
6 days ago [-]
a99c43f2d565504 6 days ago [-]
Zig kernel when
bigfishrunning 6 days ago [-]
When someone writes one
fithisux 5 days ago [-]
Now we need Rust Windows compatible kernel to save us from Recall.
rpgraham84 6 days ago [-]
oh cool, now I can have an unverifiable kernel from a team in China
weinzierl 6 days ago [-]
Decades ago Linus Torvalds was asked in an interview if he feared Linux to be replaced by something new. His answer was that some day someone young and hungry would
come along, but unless they liked writing device drivers Linux would be safe.
This is all paraphrased from my memory, so take it with a grain of salt. I think the gist of it is still valid: Projects like Asterinas are interesting and have a place, but they will not replace Linux as we have it today.
(Asterinas, from what I understood, doesn't claim to replace Linux, but it a common expectation.)
loeg 6 days ago [-]
More recently, in a similar vein:
> Torvalds seemed optimistic that "some clueless young person will decide 'how hard can it be?'" and start their own operating system in Rust or some other language. If they keep at it "for many, many decades", they may get somewhere; "I am looking forward to seeing that". Hohndel clarified that by "clueless", Torvalds was referring to his younger self; "Oh, absolutely, yeah, you have to be all kinds of stupid to say 'I can do this'", he said to more laughter. He could not have done it without the "literally tens of thousands of other people"; the "only reason I ever started was that I didn't know how hard it would be, but that's what makes it fun".
> Hohndel clarified that by "clueless", Torvalds was referring to his younger self
As the saying goes "We do this not because it is easy, but because we thought it would be easy."
Occasionally these are starts of great things.
nickpsecurity 6 days ago [-]
Sometimes, we do such things because it’s hard. We enjoy the challenge. Those that succeed are glad to make it, too.
dathinab 6 days ago [-]
but most times, even in such cases, people underestimate or not estimate at all the "hard task they do as a challenge" it's kinda part of the whole thing
BodyCulture 6 days ago [-]
Sometimes we just don’t know if a person that started something did know how hard it would be or not. Sometimes it is not possible to know how hard things can be or not.
Generally this is a very interesting question hat could be discussed in a very long thread, but still the reader will not get any value from it.
m463 6 days ago [-]
"You are enthusiastic and write kernel device drivers in rust. Write a device driver for an Intel i350 4 Port gigabit ethernet controller"
senko 6 days ago [-]
You jest, but I believe @tptacek is using an LLM (ChatGPT?) to understand the details of various Linux kernel subsystem and has said it works quite well for the task.
It's not a great jump from that to "port Linux device driver for XYZ to this new OS in Rust". Won't be perfect but a lot less hassle than doing it from scratch.
NetOpWibby 6 days ago [-]
Some future VC-funded company will unironically have this same requirement
m463 6 days ago [-]
It wasn't a requirement, it was a prompt :)
NetOpWibby 6 days ago [-]
Haha damn, it’s so obvious now. I should be asleep.
Y_Y 6 days ago [-]
Claude Sonnet 3.5 seemed happy enough to do it, and the start looked promising
Absolutely! Let's dive into writing a device driver for the Intel i350 4 Port Gigabit Ethernet Controller using Rust. This is an exciting project that combines low-level hardware interaction with the safety and performance benefits of Rust. I'll create a basic structure for our driver, focusing on the key components needed to interact with the device.
#![no_std]
#![feature(abi_x86_interrupt)]
...
but I'm not qualified to judge the quality from eyeballing and I'm certainly not going to go to the trouble of trying to test it.
m463 5 days ago [-]
"You are a pessimistic and pedantic tester of device drivers. test the following device driver for conformance to the rust language, to the kernel api, to hardening standards, judging the quality following iso 29119."
sshine 6 days ago [-]
LLMs are notoriously bad at improvising device drivers in no-std Rust.
mdhb 6 days ago [-]
Also this mysterious new Fuchsia OS from Google is also shooting for full Linux compatibility and is about to show up in Android, I think this is a much more realistic path of the next generation of operating systems that have a real chance to replace Linux but who knows what their actual plans are here at the moment but I don’t believe for a moment that that project is dead in any way.
vbezhenar 6 days ago [-]
I wonder if decision for stable syscalls was genius? Like imagine that Linux syscalls will become what C ABI is now. And there will be multiple compatible kernels, so you can choose any and run the same userspace.
surajrmal 6 days ago [-]
Why would you want to support multiple? New versions should always be backwards compatible with older ones, so you'll always have the largest amount of compatibility by targeting the latest upstream. The real challenge comes with supporting applications that want features only available in forked kernels, which I guess could prompt wanting multiple kernels targeting the distinct ABIs.
vbezhenar 6 days ago [-]
You can ask the same question about libc, yet there are several competing implementations. Yes, compatibility is not perfect and there are applications which won't work on musl, but still plenty of applications do.
lifty 6 days ago [-]
Can you give more details about it being used in Android? I thought they started using it in some small devices like nest but haven’t heard anything about Android
mdhb 6 days ago [-]
It’s about to turn up inside Android running in a VM [1] but it was less clear exactly for what purpose.
My theory is that this is essentially a long term project to bring the core of Chrome OS and Android to rely on Fuschia for its core which gives them syscall level compatibility with what they both use at the moment and that they would both essentially sit as products on top of that.
This is essentially the exact strategy they used if I remember correctly with the Nest devices where they swapped out the core and left the product on top entirely unchanged. Beyond that in a longer term scenario we might also just see a Fuchsia OS as a combined mobile / desktop workstation setup and I think part of that is also why we are seeing ChromeOS starting to take a dependency on Android’s networking stack as well right now.
I feel like there's a potentially large audience for a kernel that targets running in a VM. For a lot of workloads, a simple VM kernel could be a win.
yjftsjthsd-h 6 days ago [-]
How is that different from Linux with all virtio drivers? (You can just not compile real hardware drivers)
lmm 6 days ago [-]
The point is it would be better than Linux in whatever way that was the reason you were writing it, but you don't have to write hundreds of different device drivers to make your cool new kernel usable.
m463 6 days ago [-]
I would imagine that virtualized device drivers would have a well-defined api and vastly simplified logic.
prmoustache 6 days ago [-]
Shouldn't we start building hardware that have a builtin translation layer that makes them driveable by virtio drivers themselves? At least for the most capabilities?
SirGiggles 5 days ago [-]
I might be misremembering but I recall that Nvidia's BlueField DPUs use virtio when communicating with the host machine. From what I gather searching around it's virtio-net in specific
yjftsjthsd-h 6 days ago [-]
I imagine they do. But given that Linux has those simple drivers, why not use them?
rcxdude 6 days ago [-]
If it's written in rust, you might expect less security vulnerabilities (especially if the codebase is also smaller: NB this is potentially counterbalanced by the many eyes on linux). Maybe there would be some extra features you find useful.
lmm 6 days ago [-]
Those workloads would probably be better off as unikernels that can run directly on the VM, avoiding the question of which kernel to use entirely.
rcxdude 6 days ago [-]
There's a difference between "want to run an application with as little extra move parts on a VM" and "want to take an existing system and swap out for a kernel with some better properties, even if it means needing to run it in a VM"
pjmlp 6 days ago [-]
This is already the reality today with native cloud computing, managed runtimes.
It doesn't matter how the language gets deployed, if the runtime is on a container, a distroless container, or directly running on an hypervisor.
The runtime provides enough OS like services for the programming language purposes.
prmoustache 6 days ago [-]
this x1000
Provided you have virtio support you are ticking a lot of boxes already.
eyberg 6 days ago [-]
This is a very large rationale for what we are building with https://nanos.org .
GoblinSlayer 6 days ago [-]
Just ask an AI to riir linux drivers. Anybody tried it?
6 days ago [-]
havaker 6 days ago [-]
The license choice is explained with the following:
> [...] we accommodate the business need for proprietary kernel modules. Unlike GPL, the MPL permits the linking of MPL-covered files with proprietary code.
Glancing at the readme, it also looks like they are treating it as a big feature:
> Asterinas surpasses Linux in terms of developer friendliness. It empowers kernel developers to [...] choose between releasing their kernel modules as open source or keeping them proprietary, thanks to the flexibility offered by MPL.
Can't wait to glue some proprietary blobs to this new, secure rust kernel /s
yjftsjthsd-h 6 days ago [-]
I'm curious about the practical aspect: Are they going to freeze a stable driver ABI, or are they going to break proprietary drivers from time to time?
gpm 6 days ago [-]
Considering their OS as a framework approach I would guess they are more likely to expose a stable API than a stable ABI. Which also plays well with the MPL license (source file based) rather than something like the LGPL (~linking based).
throw4950sh06 6 days ago [-]
This is the most interesting new OS I have seen in many years.
prmoustache 6 days ago [-]
> docker run -it --privileged --network=host --device=/dev/kvm -v $(pwd)/asterinas:/root/asterinas asterinas/asterinas:0.9.3
Is that the new generation of curl | bashism in action?
oefrha 6 days ago [-]
Hardly different from downloading random binary installers and executing them. Or random source distributions and (sudo) make install. Or npm/pip/cargo/etc. install random packages. Before anyone mentions distros and package managers, as a former team member of a major package manager I can assure you we don’t vet shit beyond project notability, and new versions are accepted semi-automatically. We’ll yank something after the fact if you report a malicious update, sure.
curl | bash has an actual problem: potential execution of an incomplete script (which can be mitigated with function calling). And there’s the mostly theoretical problem of the server being pwned / sending malicious code just to you (which of course also applies to any other unsigned channel). Arbitrary code execution is never a problem unique to it, but people dunk on it all the time because they saw another person dunking on it in the past.
hnfong 6 days ago [-]
> as a former team member of a major package manager I can assure you we don’t vet shit beyond project notability, and new versions are accepted semi-automatically
Is the "--privileged" option ironic here? The project is very interesting, but it feels a bit pedantic, especially when emphasizing Rust's safety features while downplaying Linux. At the same time, it seems they're not fully applying those principles themselves, which makes it feel like they're not quite 'eating their own lunch'.
prmoustache 6 days ago [-]
A bit below in the github readme there is a link to the handbook where they explain how to build and run the project using cargo:
Linux is mostly a decades long maintained repository of real hardware programing code, and written in mostly simple "kernel" 'C', not some ultra complex syntax language (unfortunately, it has been tied to compiler specific extensions or "modern C" tantrums, _generic for instance).
Have a look at AMD GPU driver. Massive, and full of 'stabilization/work around' code... happening all the time, for years.
I guess, the real "first thing first" is to design hardware, performant hardware on latest silicon process , with a, as simple as possible, modern, standard and stable hardware programing interface. Because, for many types of hardware, 'now we know how to do it properly' (command hardware ring buffers usually, or a good compromise for modern CPU architecture, like RISC-V).
Another angle of "cleanup", I guess it would be the removal of many of the C compiler extension (or "modern C") tantrums from linux, or at least proper alternatives with not-inline assembly to allow small and alternative compilers to step in.
Personally, I tend to write rv64 assembly (which I interpret on x86_64), but for the userland. If I code C, I push towards mostly "simple and plain C99".
The more I think about it, the more I get the following coming to my mind: 'hardware with simple standard interfaces' and standard assembly for the kernel.
artemonster 6 days ago [-]
Huh? What is this nonsense?? Are you suggesting that you like to write practical-oriented, simple and working solutions instead of yak shaving half a day at perfecting ridiculous type signatures, removing „unsafe“ code and satisfying borrow checker? Proposterous! /s
This is one of the nicer ones.
It looks pretty conservative in it's use of Rust's advanced features. The code looks pretty easy to read and follow. There's actually a decent amount of comments (for rust code).
Not bad!
But then there's this Arc, Ref, Pinning and what not - how deep is that rabbit hole?
Lifetimes aren't bad, the learning curve is admittedly a bit high. Post-v1 rust significantly reduced the number of places you need them and a recent update allows you to elide them even more if memory serves.
Arc isn't any different than other languages, not sure what you're referring to by ref but a reference is just a pointer with added semantic guarantees, and Pin isn't necessary unless you're doing async (not a single Pin shows up in the kernel thus far and I can't imagine why I'd have one going forward).
Pin leverages the type system to expose to the programmer receiving a pointer to a Pin'ned object, that this object has some pointer on itself (a self referencial struct). You better be mindful not to move this object to a different memory location unless you know for sure that it is safe to do so. The Pin abstraction makes it harder to forget; and easier to notice during code review; by forcing you to use the keyword unsafe for any operations on the pinned object that could move it around.
In C, there is no such way to warn the programmer besides documentation. It is up to the programmer to be very careful.
The kernel is doing so much anyway with memory maps and flipping in / out pages for scheduling and context switching that Pin doesn't add any value in such cases anyway.
It was also specifically built for async rust. I've never personally seen it in the wild in any other context.
But what about tools like valgrind in context of C?
There was so little trust in the fragility of the original, it took a few months to convince everyone the refactored TS branch was safe.
After that, feature development was a lot faster in terms of productivity again.
Rust was a great idea, before LLMs, but I don't see the motivation for Rust when LLMs can be the solution initial for C/C++ 'problems'.
even if the LLM is trained on flawless C code (which it isn't) it still has no way of reasoning about a complex system, it's just "what token is statistically most likely to come next"
What tends to make Rust complex is advanced use of traits, generics, iterators, closures, wrapper types, async, error types… You start getting these massive semi-autogenerated nested types, the syntax sugar starts generating complex logic for you in the background that you cannot see but have to keep in mind.
It’s tempting to use the advanced type system to encode and enforce complex API semantics, using Rust almost like a formal verifier / theorem prover. But things can easily become overwhelming down that rabbit hole.
- Overall too complex
- Wrong philosophy: demanding the user to solve problems instead of solving problems for the user
- Trying to provide infinite backwards compatibility with crates, which leads to hidden bitrot
- Slow compilation times
- Claims to be "safe" but allows arbitrary unsafe code, and it's everywhere.
- Adding features to fix misfeatures (e.g. all that lifetime cruft; arc pointers) instead of fixing the underlying problem
- Hiding implementations with leaky abstractions (traits)
- Going at great length to avoid existing solutions so users re-invent it (e.g. OOP with inheritance; GC), or worse, invent more complex paradigms to work around the lack (e.g. some Rust GUI efforts; all those smart pointer types to work around the lack of GC)
- A horrendous convoluted syntax that encourages bad programming style: lot's of unwrap, and_then, etc. that makes programs hard to read and audit.
- Rust's safe code is not safe: "Rust’s safety guarantees do not include a guarantee that destructors will always run. [...] Thus, allowing mem::forget from safe code does not fundamentally change Rust’s safety guarantees."
It already has similar complexity and cognitive demands as C++ and it's going to get worse. IMHO, that's also why it's popular. Programmers love shitty languages that allow them to show off. Boring is good.
Sigh. This is not true. Not the first part, and especially not the last part. `Unsafe` doesn't allow arbitrary, unsafe code. It resets the compiler to a level where most manually managed languages are all the time. You still have to uphold all guarantees the compiler provides, just manually. That's why Miri exists.
Completely subjective. I've learned all there is to learn about Rust's syntax and most of its standard libraries, I think, and it's really not all that, in my personal opinion. There are certainly much more complex languages out there, even dynamic languages. I'd argue Typescript is more complex than Rust as a language.
> Wrong philosophy: demanding the user to solve problems instead of solving problems for the user
I have no idea what you mean by this. Do you mean you want more magic?
> Trying to provide infinite backwards compatibility with crates, which leads to hidden bitrot
Backwards compatibility reduces bitrot. Bitrot is when the ecosystem has moved on to a point of not supporting features used by stale code, thus making the code partially or completely unusable in newer environments as time progresses and the code doesn't update.
The Rust editions explicitly and definitively solve the bitrot problem, so I'm not sure what you're on about here.
> Slow compilation times
Sure, of course. That's really the biggest complaint most people have, though I've had C++ programs take just as long. Really depends on how the code is structured.
> Claims to be "safe" but allows arbitrary unsafe code, and it's everywhere.
Unsafe isn't a license to kill. It also doesn't allow "arbitrary" code. I suggest reading the rustnomicon, the book about Rust undefined behavior. All `unsafe` code must adhere to the postcondition that no undefined behavior is present. It also doesn't remove borrow checking and the like. Without `unsafe` you couldn't do really anything that a systems language would need to do in certain cases - e.g. writing a kernel requires doing inherently unsafe things (e.g. switching out CR3) where no compiler on earth currently written will understand those semantics.
People seem to parrot this same "unsafe nullifies rust's safety" without really understanding it. I suppose they could have renamed the `unsafe` keyword `code_the_does_stuff_unverifiable_by_the_compiler_so_must_still_adhere_to_well_formed_postrequisites_at_risk_of_invoking_undefined_behavior` but alas I think it'd be pretty annoying to write that so often.
It's pretty typical to abstract away `unsafe` code into a safe API, as most crates do.
> Adding features to fix misfeatures (e.g. all that lifetime cruft; arc pointers) instead of fixing the underlying problem
Lifetimes aren't "cruft", not sure what you mean. They've also been elided in a ton of cases.
An "arc pointer" isn't a thing; there's ARC (which is present in every unmanaged language, including C++, Objective-C, Swift, etc). I'm not sure what the "underlying problem" is you're referring to. Rust takes the position that the standard library shouldn't automatically make e.g. Mutexes an atomically reference counted abstraction, but instead allow the user to determine if reference counting if even necessary (Rc<Mutex>) and if it should be atomic so as to be shareable across cores (Arc<Mutex>). This type composure is exactly why Rust's type system is so easy to work with, refactor and optimize.
> Hiding implementations with leaky abstractions (traits)
Sorry for being blunt but this is a word salad. Traits aren't leaky abstractions. In my personal experience they compose so, so much better and have better optimization strategies than more rigid OOP class hierarchies. So I'm not sure what you mean here.
> Going at great length to avoid existing solutions so users re-invent it (e.g. OOP with inheritance; GC), or worse, invent more complex paradigms to work around the lack (e.g. some Rust GUI efforts; all those smart pointer types to work around the lack of GC)
Trait theory has been around for ages. GC is not a silver bullet and I wish people would stop pretending it was. There are endless drawbacks to GC. "All those smart pointer types" -- which ones? You just seem to want GC. I'm not sure why you want GC. GC solves few problems and creates many more. It can't be used in a ton of environments, either.
> A horrendous convoluted syntax that encourages bad programming style: lot's of unwrap, and_then, etc. that makes programs hard to read and audit.
This is completely subjective. And no, there's not a lot of `and_then`, I don't think you've read much Rust. Sorry if I'm sounding rude, but it's clear to me by this point in my response that you've played with the language only at a very surface level and have come to some pretty strong (and wrong) conclusions about it.
If you don't like it, fine, but don't try to assert it as being a bad language and imply something about the people that use it or work on it.
> Rust's safe code is not safe: "Rust’s safety guarantees do not include a guarantee that destructors will always run. [...] Thus, allowing mem::forget from safe code does not fundamentally change Rust’s safety guarantees."
You misunderstand what it's saying there but I'm honestly tired of rehashing stuff that's very easily researched that you seem to not be willing to do.
As long as the Rust fans stick to their favorite language, everybody can be happy.
Arc is nothing more than reference counting. C++ can do that too, and I'm sure there are C libraries for it. That's not an admission of anything, it's actually solving the problem rather than ignoring it and hoping it doesn't crash your program in fun and unexpected ways.
Using Arc also comes with a performance hit because validation needs to be done at runtime. You can go back to the faster C/C++ style data exchange by wrapping your code in unsafe {} blocks, though, but the risks of memory corruption, concurrent access, and using deallocated memory are on you if you do it, and those are generally the whole reason people pick Rust over C++ in the first place.
No. I've written code that returns Result<Option<T>>. It was a wrapper for a server's query web API.
The Result part determines whether the request succeeded and the response is valid.
The Option part is because the parameter being queried might not exist. For example, if I ask the API for the current state of the user session with a given Session ID, but that Session ID does not exist, then the Rust wrapper could return OK(None) meaning that the request succeeded, but that no such session was found.
That is why a query that successfully returns no items can be represented as Ok(None).
A successful query with items returned would instead be Ok(Vec<Item>).
An error in the completing the query (for example, problem with the database), would be Err(DatabaseError) or Err(SomeOtherError).
But in this case, a query using an invalid session ID is not an error. It is asking for details about something that does not exist.
>> cf File::open that could return Result<Option<File>> if file is not found.
This type of query is not like File::open which gets a handle to a resource. Trying to get a handle to a resource that does not exist is an error.
This type of query is read-only and does not allocate any resources or prepare to do anything with the session.
It simplifies the control flow because it distinguishes between errors in completing a query versus the presence or absence of items returned from the query.
Documentation and how SQL database queries work.
The documentation states that a valid session id will return a SessionInfo struct (since it is an Option the type is Some(SessionInfo) ), and that an invalid session id will return None.
If the SQL query is something like "SELECT * FROM USER_SESSIONS WHERE USER_SESSION_ID = $1" then if an invalid session id is provided the database returns zero rows. The query was successful, but there were no matching sessions with that session id.
>> You have conflated empty response with an erroneous situation. The simplest solution is just Result<T, E>.
Again, an empty response is not an error in this situation. If your database query returns zero rows, is it an error? The database query succeeded. There are no sessions with the provided session id. What error occurred?
- Technical problem (like connection problems) means I don't know what's in the db
- No technical problem, but no user entry
- No technical problem, and a user entry
You need the Result for the technical problems, and the Option for whether there's a user entry or not.
The _static_ borrow checker can only check what is _statically_ verifiable, which is but a subset of valid programs. There are few things more frustrating than doing something you know is correct, but that you cannot express in your language.
Several kernels for example use type-stable memory, memory that is guaranteed to only hold objects of a particular type, though perhaps only providing that guarantee for as long as you hold an RCU read-lock (this is the case in Linux with SLAB_TYPESAFE_BY_RCU). It is possible in some cases to be able to safely deal with references to objects where the "lifetime" of the referent has ended, but where by dint of it being guaranteed to be the same type of object, you can still do what you want to do.
This comes in handy when you have a problem that commonly appears in kernels where you need to invert a typical lock ordering (a classic case is that the page fault codepath might want to lock, say, VM object then page queue, but the page-replacement codepath will want to lock page-queue then VM object.)
Unfortunately it's hard to think of how the preconditions for these tricks could be formally expressed.
There are lots of options if you want.
But in that case you're stuck paying the overhead 100% of the time, even though 90% of the lifetimes are simple. (Perhaps a little less so with escape analysis etc., but doing it at compile time in a way that's understandable in the source feels a lot more reliable)
So lemme ask: what other languages and project (open/closed, big/small, web/mobile/desktop, game/consumerapp/bizapp) have you experience with as to come to this conclusion?
If you're just starting out or doing something relatively simple, your goal is to get something working. This is so true regardless of the language.
But like I said, I've not looked at any Rust despite its marketing success.
I find a lot of the complexities tend to come from devs with more experience in communities that tend to add complexity by nature (C# and Java devs in particular). YMMV of course, that's just been my take so far. I've written a few simple web (micro)services in Rust and a couple of playground Tauri apps. I will say the simpler tasks have been incredibly easy to work through.
Though I may not have always taken the absolutely most performant, least memory path of work, it's been smaller/faster than other platforms and languages I have more experience with. And that's without even getting into build/compile time optimization options.
Intuition tells me that Rust is young enough to attract a certain type of early adopter, the kind of programmer who is more likely to document their code well from the outset.
The big concern I have however is hardware support, specifically networking hardware.
I think a very interesting approach would be to boot the machine with a FreeBSD or Linux kernel, just for the purposes of hardware as well as network support, and use a sort of Rust OS/abstraction layer for the rest, bypassing or simply not using the originally booted kernel for all user land specific stuff.
That's basically what you're getting with Docker containers and a shared kernel. AWS Lambda is doing something similar with dedicated kernels with Firecracker VMs
Basically single app directly to network (the world) and as little as possible else in between.
The complexity on the other hand is architectural and logical to achieve scale to hundreds of CPUs, maximise bandwidth and reduce latency as much as possible.
Any normal Rust kernel will either have issues scaling on multi-cores or use tax-heavy synchronisation primitives. The kernel RCU and lock-free algorithm took a long time to be discovered and become mature and optimised aggressively to cater for the complex modern computer architectures of out-of-order execution, pipelining, complex memory hierarchies (especially when it comes to caching) and NUMA.
Why would that be the case at all? What has Rust anything to do with that?
To reach a useful state, you only need to be highly performant on a handful of currently popular server architectures.
> Any normal Rust kernel will either have issues scaling on multi-cores or use tax-heavy synchronisation primitives.
I'm not sure how that applies to Asterinas. Is Asterinas any normal Rust kernel?
https://asterinas.github.io/book/kernel/the-framekernel-arch...
You can check out hardware support here: https://core.dpdk.org/supported/nics/
Their conclusion is io_uring is still slower but not by much, and future improvements may make the difference negligible. So you're right, at least in part. Given the tradeoffs, DPDK may not be worth it anymore.
Wut? More than 10 years ago, a cheap beige box could saturated a 1Gbps link with a kernel as it came from e.g. Debian w/o special tuning. A somewhat more expensive box could get a good share of a 10Gbps link (using Jumbo frames), so these new results are, er, somewhat underwhelming.
"SR-IOV was used on the NIC to enable the use of virtual functions, as it was the only NIC that was available during the study for testing and therefore the use of virtual functions was a necessity for conducting the experiments."
A lot of the benefit of dpdk is colocating your data and network stack in the same virtual memory context. io_uring I can see getting you there if you have you're serving fixed files as a cdn kind of like netflix's appliances, but for cases where you're actually doing branchy work on the individual requests, dpdk is probably a little easier to scale up to the faster network cards.
p.s.: i was wrong
>While we prioritize compatibility, it is important to note that Asterinas does not, nor will it in the future, support the loading of Linux kernel modules.
https://asterinas.github.io/book/kernel/linux-compatibility....
lol. No. They just added a CPU and then offloaded all the closed source userspace driver code to it leaving behind the same dumb open sourceable kernel driver shim as before (ie instead of talking to userspace it talks to the GPU’s CPU).
> The past 30 years of the Linux kernel's evolution has proven that there is no need for a stable kernel ABI.
What the last 30 years have shown is that there is actually a need for it, otherwise DKMS wouldn’t be a thing. Heck, intel’s performance profiler can’t keep up with the kernel changes which means you get to pick running an up to date kernel or be able to use the open source out-of-tree kernel module. The fact that Linux is alone in this should make it clear it’s wrong. Heck Android even wrote their own HAL to try to make it possible to update the kernel on older devices. It’s an economics problem that the Linux kernel gets to pretend doesn’t exist but it’s a bad philosophical position. It’s possible to support refactoring and porting to new platforms while providing ABI compatibility and Linux is way past the point where it would even be a minor inconvenience - all the code has ossified quite a bit anyway.
My experience of using Linux and having devices that used to work become unsupported suggests just the opposite.
> While we prioritize compatibility, it is important to note that Asterinas does not, nor will it in the future, support the loading of Linux kernel modules.
It’s probably easier if the kernel’s key goal is to be compatible with the Linux ABI rather than being compatible with its earlier self while bolting on Linux compatibility.
I was hired at Joyent largely to work on bhyve so that Triton and Joyent’s public cloud had a way to run Linux VMs when full Linux compatibility was more important than the efficiency of zones/containers.
and emulate the virtual filesystems (/proc/...)
They might not yet implement everything that's needed to boot a standard Linux userland but you could say boot straight into a web server built for Linux, instead of booting into init for example.
https://www.redox-os.org/
Thus it is a much more interesting project.
You still have kernel modules for microkernel-like functionality
> utilize the more productive Rust programming language
Nitpick: it’s 2024 and these ‘more productive’ comparisons are silly, completely unscientific, And a bit of a red flag for your project: The most productive language for a developer is the one they understand what is happening one layer below the level of abstraction they are working with. Unless you’re comparing something rating Ruby vs RiscV assembly, it’s just hocus-pocus.
FWIW that’s what the Linux compatibility layer in the BSDs does and also what WSL 1 did (https://jmmv.dev/2020/11/wsl-lost-potential.html).
It’s hard to get _everything_ perfectly right but not that difficult to get most of it working.
The company I work for has both rust and python projects (through partially pre "reasonable python type linting" using mypy and co.) and the general consensus there is "overall" rust is noticeable more productive (and stable in usage/reliable), especially if you have code which changes a lot.
A company I worked previous for had used rust in the very early days (around 1.0 days) and had one of this "let's throw up a huge prototype code base in a matter of days and then rewrite it later" (basically 90% of code had huge tech dept). But that code base stuck around way longer then intended, caused way less issues then expected. I had to maintain it a bit and in my experience with similar code in Python and Js (and a bit Jave) I expected it to be very painful but surprisingly it wasn't, like at all.
Similar comparing my experience massive time wastes due to having to debug soundness/UB issues in Rust, with experiences in C/C++ it's again way more productive.
So as long as you don't do bad stuff like over obsessing with the type system everything in my experience tells me using Rust is more productive (for many tasks, definitely not all task, there are some really grate frameworks doing a ton of work for you in some languages against which the rust ecosystem atm. can't compete).
---
> Most productive language for a developer is the one they understand what is happening one layer below the level of abstraction they are working with.
I strongly disagree, the most productive language is the one where the developer doesn't have to care much about what happens in a layer below in most cases. At least as long as you don't want obsess over micro optimizations not being worth the time and opportunity cost they come with for most companies/use cases.
You look at Linux's syscall table[0], read through the documentation to figure out the arguments, data types, flags, return values, etc., and then implement that in your kernel. The Linux ABI is just its "library" interface to userspace.
It's probably not that difficult; writing the rest of the kernel itself is more challenging, and, frankly, more interesting. Certainly matching behavior and semantics can be tricky sometimes, I'm sure. And I wouldn't be surprised if the initial implementation of some things (like io_uring, for example, if it's even supported yet) might be primitive and poorly optimized, or might even use other syscalls to do their work.
But it's doable. While Linux's internal ABI is unstable, the syscall interface is sacred. One of Torvalds' golden rules is you don't break userspace.
[0] https://filippo.io/linux-syscall-table/
As well as some subset of the files expected in /dev, /proc, /sys, and similar, which are also part of the userspace ABI. And the startup mechanisms for processes, and the layout of AUXV...
It's absolutely doable, but the interface is wider than just the syscall layer.
Ah good times.
https://tockos.org/
From the looks of it, this seems like a serious corporate backed project made by employees of the Ant Group, the chinese fintech giant. A more fair comparison would be with Google's Fuchsia OS (defunct) or Huawei's HarmonyOS. It may succeed, it may fail, but it's nothing like a couple of kids doing a passion project to learn Rust.
Its more of a research OS but still cool.
https://gitlab.com/uxrt
Unprivileged services can exploit known compiler bugs and do anything they want in safe Rust. How this affects their security model?
¹ https://github.com/nuta/kerla/
I guess it depends on what they mean by "easy". Certainly it's easier in the sense that you can just write code all day long, and not have to deal with the politics about Rust inside Linux, or deal with all the existing C interfaces, finding ways to wrap them in Rust in good, useful ways that leverage Rust's strengths but don't make it harder to evolve those C interfaces without trouble on the Rust side.
But the bulk of Linux is device drivers. You can build a kernel in Rust (like Asterinas) that can run all of a regular Linux userland without recompilation, and I imagine it's maybe not even that difficult to do so. But Asterinas only runs on x86_64 VMs right now, and won't run on real hardware. Getting to the point where it could -- especially on modern hardware -- might take years. Supporting all the architectures and various bits of hardware that Linux supports could take decades. I suppose limiting themselves to three or four architectures, and only supporting hardware made more recently could cut that down. But still, it's a daunting project.
> Currently, Asterinas only supports x86-64 VMs. However, our aim for 2024 is to make Asterinas production-ready on x86-64 VMs.
I'm confused.
> By 2024, we aim to achieve production-ready status for VM environments on x86-64. > In 2025 and beyond, we will expand our support for CPU architectures and hardware devices.
https://asterinas.github.io/book/kernel/roadmap.html
https://github.com/asterinas/asterinas/issues/669
They've been working on it for a while so they can get rust into the linux kernel
There's no specification of that ABI, much less a compliance test suite. How complete is this compatibility?
https://linux-test-project.readthedocs.io/en/latest/
https://asterinas.github.io/book/kernel/linux-compatibility....
Let's take example of network. There's IP address, gateway, DNS, routes etc. Depending on distribution we might see something like netplan reading config files and then calling ABI functions?
Or Linux kernel directly also reads some config files? Probably not...
Edit: looks like iproute2 uses NETLINK, but non-networking tools might use syscalls or device ioctls.
https://en.m.wikipedia.org/wiki/Netlink
Sure is a lot of text to say: We try to use unsafe as little as possible.
Which is the minimum you'd expect anyways ¯\_(ツ)_/¯
0. https://asterinas.github.io/book/kernel/the-framekernel-arch...
Does it mean it can re-use the drivers written for hardware to run with linux ?
I guess the NT kernel needs to. Does Darwin?
> Currently, Asterinas only supports x86-64 VMs.
So no real hardware.
As soon as I can financially retire, I'll make contributing to this my full time job!
If this catches on and has generally been subject to significant third party code review with positive results, I'm not sure any backdoor is lower cost to use than an equivalent linux vulnerability. To be fair, I'm not sure it isn't either.
That's an interesting example because Huawei equipment is currently being removed by several Western countries (UK, Canada, US, Germany) specifically because it's Chinese.
https://www.nytimes.com/2024/07/11/business/huawei-germany-b...
https://www.cbc.ca/news/politics/huawei-5g-decision-1.631083...
https://www.gov.uk/government/news/huawei-to-be-removed-from...
https://www.reuters.com/business/media-telecom/us-open-progr...
> If everything goes well, Asterinas is now up and running inside a VM.
Seems like the developers are very confident about it too
This is all paraphrased from my memory, so take it with a grain of salt. I think the gist of it is still valid: Projects like Asterinas are interesting and have a place, but they will not replace Linux as we have it today.
(Asterinas, from what I understood, doesn't claim to replace Linux, but it a common expectation.)
> Torvalds seemed optimistic that "some clueless young person will decide 'how hard can it be?'" and start their own operating system in Rust or some other language. If they keep at it "for many, many decades", they may get somewhere; "I am looking forward to seeing that". Hohndel clarified that by "clueless", Torvalds was referring to his younger self; "Oh, absolutely, yeah, you have to be all kinds of stupid to say 'I can do this'", he said to more laughter. He could not have done it without the "literally tens of thousands of other people"; the "only reason I ever started was that I didn't know how hard it would be, but that's what makes it fun".
https://lwn.net/Articles/990534/
As the saying goes "We do this not because it is easy, but because we thought it would be easy."
Occasionally these are starts of great things.
Generally this is a very interesting question hat could be discussed in a very long thread, but still the reader will not get any value from it.
It's not a great jump from that to "port Linux device driver for XYZ to this new OS in Rust". Won't be perfect but a lot less hassle than doing it from scratch.
My theory is that this is essentially a long term project to bring the core of Chrome OS and Android to rely on Fuschia for its core which gives them syscall level compatibility with what they both use at the moment and that they would both essentially sit as products on top of that.
This is essentially the exact strategy they used if I remember correctly with the Nest devices where they swapped out the core and left the product on top entirely unchanged. Beyond that in a longer term scenario we might also just see a Fuchsia OS as a combined mobile / desktop workstation setup and I think part of that is also why we are seeing ChromeOS starting to take a dependency on Android’s networking stack as well right now.
[1] https://www.androidauthority.com/microfuchsia-on-android-345...
It doesn't matter how the language gets deployed, if the runtime is on a container, a distroless container, or directly running on an hypervisor.
The runtime provides enough OS like services for the programming language purposes.
Provided you have virtio support you are ticking a lot of boxes already.
> [...] we accommodate the business need for proprietary kernel modules. Unlike GPL, the MPL permits the linking of MPL-covered files with proprietary code.
Glancing at the readme, it also looks like they are treating it as a big feature:
> Asterinas surpasses Linux in terms of developer friendliness. It empowers kernel developers to [...] choose between releasing their kernel modules as open source or keeping them proprietary, thanks to the flexibility offered by MPL.
Can't wait to glue some proprietary blobs to this new, secure rust kernel /s
Is that the new generation of curl | bashism in action?
curl | bash has an actual problem: potential execution of an incomplete script (which can be mitigated with function calling). And there’s the mostly theoretical problem of the server being pwned / sending malicious code just to you (which of course also applies to any other unsigned channel). Arbitrary code execution is never a problem unique to it, but people dunk on it all the time because they saw another person dunking on it in the past.
An example that illustrates this: https://lwn.net/Articles/22991/
(And wow, it's been 22 years already...?)
https://asterinas.github.io/book/osdk/guide/run-project.html
Have a look at AMD GPU driver. Massive, and full of 'stabilization/work around' code... happening all the time, for years.
I guess, the real "first thing first" is to design hardware, performant hardware on latest silicon process , with a, as simple as possible, modern, standard and stable hardware programing interface. Because, for many types of hardware, 'now we know how to do it properly' (command hardware ring buffers usually, or a good compromise for modern CPU architecture, like RISC-V).
Another angle of "cleanup", I guess it would be the removal of many of the C compiler extension (or "modern C") tantrums from linux, or at least proper alternatives with not-inline assembly to allow small and alternative compilers to step in.
Personally, I tend to write rv64 assembly (which I interpret on x86_64), but for the userland. If I code C, I push towards mostly "simple and plain C99".
The more I think about it, the more I get the following coming to my mind: 'hardware with simple standard interfaces' and standard assembly for the kernel.