Rust "makes programming fun again".

Most of my Delphi functions are wrappers for the Win32 API.

When possible I write to the underlying API to avoid the wrapper overhead.

I’ve never written C in the ‘nix environment but was curious if the same can be done directly to the ‘nix api instead of libraries and wrappers.

Thanks for the reply on how it works in ‘nix.
 
In unix user space programs, you are dealing with two separate groups of api's. User programs call interfaces in the kernel (to do things that require kernel privilege, like doing i/o, on the user program's behalf) through the unix system library; and user programs can also call functions in the standard C library (and other userland libraries) which get linked into each user program. Typically, functions in the standard C library will themselves call the system library to access the kernel when required. Calling a system library function involves a privilege transition, whereas calling a C library function does not. The system library API, also known as the POSIX system API, is defined in the C header file <unistd.h>, and you need to include that header file in your program to call the system library correctly.

The unix system library contains a set of entry points which are called 'system calls' in usual terminology. However, the 'true' system calls in unix are the kernel interfaces that the system library itself, calls internally; each call being identified by a system call number. This is somewhat analgous to the MS-DOS INT 21H mechanism, where you have a preamble that loads some values into registers (or whatever parameter passing mechanism is used), one of which is the system call number, and then it calls a software interrupt (or similar mechanism) to pass control to the kernel; and finally passes any return information back to user space. The low-level interface is documented in section 3 here https://docs.freebsd.org/en/articles/x86-assembly/ . The list of system call numbers are found in the file /usr/include/sys/syscall.h, and the corresponding system call names are defined in /usr/src/sys/kern/syscalls.c. There is a useful table of freebsd system calls here: https://alfonsosiciliano.gitlab.io/posts/2026-04-09-freebsd-16-system-calls.html . As you can see, there are quite a lot of them, some obsolete. The system library may not provide callable functions for every available system call (see note on syscall(2) below), which is the reason for the distinction drawn between the set of interfaces provided in the system library through unistd.h, and the set of real or 'true' system calls supported by the operating system. Most of the the time, its a 1:1 mapping, however, so it's normal to use the term 'system call' to mean an entry point in the system library.

You can make low-level system calls directly in unix, but it doesn't gain you anything in performance terms, since the code you write to do the job merely replicates what is already in the unix system library; and if you want your code to stay easily maintainable, it's better to use the system library, since doing it yourself exposes you to the details of the low-level ABI. There's a good description here https://en.wikipedia.org/wiki/System_call
- see the section headed "the library as an intermediary".

So for example, you would call write(2) and read(2) in the system library to call the system calls to write and read to/from a file descriptor, bypassing the C stdio library buffered i/o. The corresponding higher level C stdio library functions that do buffered i/o are fwrite(3) and fread(3); and those will internally call write(2) and read(2) respectively. Note that the system library calls are documented in section 2 of the manpages, and the C stdio (and other userland) library calls are documented in section 3 of the manpages; so you would say 'man 2 read' to see the manpage for read(2), and 'man 3 fread' to see the manpage for fread(3). And 'man 2 intro' gives you an introduction to the parameters that can be passed to system library calls, and describes the system library error handling. Indeed section 2 of the manpages is concerned with the system interface, and section 3 with the user space libraries. Finally the 'system library' I'm talking about here, does not exist as a separate object file; in fact it is part of libc, along with the user space standard C library; when you compile a C program and provide the "-lc" option, you get both linked into your program by the linker; which can be slightly confusing when people talk about the 'system library' versus the 'standard C library', what they really mean is two different sets of functions.

Occasionally (not very often) there can be some system calls which do not have wrappers in the system library, in which case you need to use the syscall(2) mechanism to call them indirectly, by their system call number, in a standardised way; of course syscall(2) is itself an entry point into the system library. So 'man 2 syscall' to read about how this works.

In general, in user-space application programs, it is desirable to use the highest level calls available (eg, the standard C library) in preferrence to calling the system library directly, unless there is a specific reason to call the system library; doing so improves portability and provides access to additional facilities provided by the standard C library, saving code replication (eg, buffered i/o in the example discussed above). Code that your write on freebsd, that calls the standard C library, should be easy to port to other operating systems, whereas code that you write, that calls freebsd system calls through the system library, may not be quite so portable, depending upon what system calls you made; things like read(2) and write(2) are pretty much universally available and are specified by POSIX, whereas others may have different signatures on other operating systems, or may not even exist at all.

This is a short introductory overview, with lots of details omitted. For homework, look up 'non-blocking i/o', and 'restartable system calls', for a couple of related topics of further interest. Of course if you search the web or github you will find many example programs, showing you how to write programs that make system calls in unix.
 
Last edited:
Without using UNSAFE except for defining interfaces to external C/asm codes, of course. 😁
The UNSAFE thing seems to defeat the whole purpose of Rust to my mind. You end up with a hodge-podge of 'safe' code mixed up with a bunch of UNSAFE code, which sounds like a maintenance nightmare to me. I suppose you can claim that at least some of the code is 'safe'. But I'm not a Rust programmer, so I'm probably talking out of my backside elbow ...
 
The UNSAFE thing seems to defeat the whole purpose of Rust to my mind.
It reduces the amount of unsafe code (where you have to do manual checking) significantly. For instance, an ongoing rewrite of a small OS (with virtual memory + processes) has about 10K likes of rust code and under 250 unsafe blocks. Another os of a similar size under 220 unsafe blocks. The redox kernel has over 40K LoC and 1146 unsafe blocks (so a very similar reduction).

Even if you separate such code out in assembly or C code, that still has to be manually checked. While guarantees provided by nim, ocaml, v, zig etc. may be less &/or different, there would be a similar decrease in manual checking through a similar language feature, and perhaps more since you can't convey richer semantics across languages.

Look at this way: once you figured out constraints & assertions that make the system work, if you can express those constraints to the compiler where it can check them for you, you have less work to do as you evolve the system.
 
Even if you separate such code out in assembly or C code, that still has to be manually checked.
Exactly. Memory safety in C / asm codes are almost purely on each developer (and optionally, reviewers). Of course need checks.

What I fear is that some non-professional / non-enthusiastic person would blindly believe that codes in Rust (or any other "memory safe" languages) is perfectly memory safe. So separating unsafe parts from Rust parts should be strongly wanted not to confuse such a person.
 
I just messed with pipewire, the new audio server. The oss API backend for it in written in Rust. The FreeBSD port uses 56 different crates. 26 of which have version numbers < 1.0. That's just one backend module, not the actual server.

Fun?
Off topic, but new USES and DEFAULT_VERSIONS would be needed for pulseaudio to allow pipewire to be used as the alternative dependency of pulseaudio.

I imagine something like USES=pulseaudio instead of directly {LIB|RUN}_DEPENDS on pulseaudio and choose one via DEFAULT_VERSIONS+= pulseaudo={pulseaudio|pipewire}.
 
Off topic, but new USES and DEFAULT_VERSIONS would be needed for pulseaudio to allow pipewire to be used as the alternative dependency of pulseaudio.

I imagine something like USES=pulseaudio instead of directly {LIB|RUN}_DEPENDS on pulseaudio and choose one via DEFAULT_VERSIONS+= pulseaudo={pulseaudio|pipewire}.
Yes, that's the way to go.

Unfortunately pw runs very badly on FreeBSD for me. jack layer just hangs and pulseaudio emulation is compiled out by default. Not sure what's up with that. Pipewire on Linux works great.
 
Wake me up when they rewrite systemd in Rust.
I believe RedoxOS does have its init system written in Rust already. As for Linux, there are active projects like this one: https://github.com/KillingSpark/rustysd

But programming in Rust being fun??? I remember seeing info on the Internet about it being so bad, people would quit over being forced to program in Rust.

But frankly, I think that 'programming being fun' is not about the choice of language, but more about the attitude of the project participants. You can program in brainfuck and have fun with it, or your can program in VB.NET and have an awful experience because you don't get to really decide anything, and nothing makes sense any more.

You can't force people to have fun. You can ask people to do something, but if you tell people to "have fun", that gets taken for mere sarcasm.
 
For my personal tinker toys, Rust fills a niche: bloody fast, single-binary output, idiot-proof build system, massive ecosystem of boilerplate ready to go. I got a fanless potato running in my metering closet taking readings for my home's energy usage. The data logger for that? I wrote that in Rust, borrowing heavily from the Cargo ecosystem. It's a single binary that I can just plonk onto the SD card of the ancient SBC that's running it, and be done with it. It takes data from a serial port, cleans that up slightly and pushes the result out to InfluxDB. The board from around 2013 would have been e-waste by now if it weren't for an application like this. Fun? Kind of! Same goes for the RPG and MS-DOS hard disk image generator that I'm working on in my spare time, also both in Rust.

The borrow checker really isn't that big of a hurdle. It forces you to think about data ownership, which is -all in all- a good thing. I also like how Rust forces you to think about the demarcation between its memory safe default, and "unsafe" constructs that let you skip those checks. Thinking is a heavily underrated activity these days, or may just be that I'm getting old.

Programming for fun in general? Well, that doesn't really depend on the language for me. I write 6502 assembly for fun. It makes my Commodore 64 go beep. I'm weird like that.
 
For my personal tinker toys, Rust fills a niche: bloody fast, single-binary output, idiot-proof build system, massive ecosystem of boilerplate ready to go. I got a fanless potato running in my metering closet taking readings for my home's energy usage. The data logger for that? I wrote that in Rust, borrowing heavily from the Cargo ecosystem. It's a single binary that I can just plonk onto the SD card of the ancient SBC that's running it, and be done with it. It takes data from a serial port, cleans that up slightly and pushes the result out to InfluxDB. The board from around 2013 would have been e-waste by now if it weren't for an application like this. Fun? Kind of! Same goes for the RPG and MS-DOS hard disk image generator that I'm working on in my spare time, also both in Rust.

The borrow checker really isn't that big of a hurdle. It forces you to think about data ownership, which is -all in all- a good thing. I also like how Rust forces you to think about the demarcation between its memory safe default, and "unsafe" constructs that let you skip those checks. Thinking is a heavily underrated activity these days, or may just be that I'm getting old.
It's good to know someone has had some good experiences of using it. It can't be all bad. :-)
 
When I walked into my first and only "agile shop". the model was generic coders taking whatever JIRA ticket the idiot lead decided to assign, expecting that every coder could do any ticket that came thru in the specified amount of time...and then being performance evaluated simply by ticket burndown rates...and lets not forget the "team standards" based code reviewed.

THIS is actually how it is :cool: ....

Agile wasn't even designed to be used this way
 
You can't force people to have fun. You can ask people to do something, but if you tell people to "have fun", that gets taken for mere sarcasm.
What he actually said was that it "makes programming fun 'again'". Somehow I didn't realise that programming in C and other existing languages had become so actively unpleasant, I must have missed something...
 
Agile.. often seems meant to facilitate the managerial brain that can't hold a coherent plan for longer than it takes a coffee to go stale. Operational agility is not necessarily a bad thing, but it's more often than not a completely irrelevant outcome. So what if you can change a system or a process twelve times a day? Who benefits from that and how? As a former product owner in the scrum treadmill I learned that in this role you're not supposed to ignore the method in favor of hammering out desired outcomes. People find you "difficult to work with". But in the end nobody gives a flying fudge about how many story points my team "burns". The real boss only ever wants outcomes. The jerk who bugs you about Jira charts? Ignore, politely if they're friendly.

As for Rust, well, I don't have any skin in this game. I am actually surprised at the amount of pushback against a programming language that -for me- fits in a legitimate niche. So does Perl.
 
Back
Top