My experiences with Rust
- Reply: Poul-Henning Kamp: "Re: My experiences with Rust"
- Reply: Vadim Goncharov : "Re: My experiences with Rust"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 22 Aug 2025 16:10:15 UTC
There was a long and hot thread about 'Rust in base' recently. Since
I did used the rust language to write some very OS-specific utilities,
I decided to share my experience. If written in C, yjr w tools would
definitely end up in base.
I do not have any huge investments in Rust, neither emotional nor
huge time spent learning it. Still, I decided to use Rust since I was
curious and the hate/love dihotomy for just a language felt weird.
I used Rust for two utilities, first one is
https://github.com/kostikbel/pollinfo ports:sysutils/pollinfo
(disclosure: the work was sponsored by The FreeBSD Foundation)
the second one is
https://github.com/kostikbel/ktcplist ports:net/ktcplist
(another disclosure: the work was sponsored by Nvidia networking BU).
In both cases, it was a common theme to retrieve system information in
the binary format by a direct syscall invocation, then provide a user-
or machine-friendly output format for consumption.
The pollinfo utility was a part of the efforts to make event wait
observable. There was a 'procstat kqueue' command added that reported
the kqueue(2) events that process wait for. Similarly, a residual
tool for select(2)/(p)poll(2) interrogation felt natural. There were
already the pre-existing kernel facilities (ptrace) that were needed
to write the tool (but transparent ptrace attach made things better,
just a disgress).
For ktcplist, the more natural action would be to extend netstat(8)
then to write a new tool, but I cannot make myself to use libxo. It
is less painful to write Rust then to try to use libxo, at least for
me. But first, I need to define and implement the kernel interface to
export the ktls connection list to userspace, unlike the pollinfo
case.
Nice things about using Rust:
- after typechecking, the program just worked. This was an experience
very similar to haskell. Of course, there were unsafe {} blocks, and
part of the good design was to contain the unsafety to only the code
that advanced iterators over the elements of the kernel returned
array. If this was followed, it was quite nice environment to work
with WRT correctness.
Problematic parts:
1.Rust uses its own so called libc bindings. This is a Rust crate
containing collections of pure bindings both to libc and kernel
interfaces. After gettting the kernel interface done, you have to
write separate patches for Rust libc and then work to upstream it,
before the new kernel feature becomes useful for Rust code. A silly
alternative is to maintain the rust libc fork, which is not
sustainable. Fortunately, the libc maintainers are very responsible
(count for a week to get a feedback).
2.Quite surprising, is the portability. It is a known sore with C
that you need to use %jd and (intmax_t) cast to get
platform-independent printing of ints/longs. For Rust, a similar
issue is the signess of char. When providing Rust libc binding, and
testing either amd64, it is very tempting to use i8 as the type for
char kernel native type, which breaks everywhere outside amd64. You
must use libc::c_char. This is due to Rust type construct being an
equivalent of C typedef.
3.It was more prominent for ktcplist then for pollinfo, so I will
explain it there. Nvidia verification team requested that ltcpdump
has machine-readable output, preferrably json. Adding serde
serialization to json was trivial, and solved the problem, by the
cost of adding another: making the small utility depend on several
dozens of the external packages. This makes it very problematic if
we ever want to allow Rust in base and include ktcpdump as part of
it.
I do not have any conclusions. I am happy that both utilities live in
ports (thanks to gleb@), and they should be left there IMO.