What is lovely about C is its paper-thin layer atop the syscall pokey bits: signal, vfork, mmap, etc. No surprise that other languages either start by using libc, or find their way there eventually.
The "killer feature" of C is the simple semantics of the language (despite all the dark undefined corners), which can be implemented relatively straightforward on a variety of ISAs. There isn't any need for runtime support because of the lack of fancy language features.
That makes it the most natural way to call into the operating system, without any concerns that the chunk of memory returned by mmap has to be somehow managed by the language runtime.
The trouble is you can step from simple semantics to dark corners through such simple things as "adding two numbers together" and "accepting user input". I do agree that the lack of need for a managed runtime is a huge advantage on embedded or small systems.
> I do agree that the lack of need for a managed runtime is a huge advantage on embedded or small systems.
Not only in embedded systems. It is a huge advantage when interfacing with the operating system from within a userland process.
Lack of a runtime means that a call to a kernel function like, say, `sched_setscheduler(2)` would not interfere with any such thread scheduling policies of the host runtime. Or that the runtime is grabbing file descriptors out of your control, making it hard to reason about resource usage.
I think that the fact that we essentially have instructions on most architectures well suited for the implementation of certain operations common in C answers this pretty well.
This is only true for UNIX based OSes, given that libc is naturally the door into the OS, and contains much more than what ISO C compliant libc is supposed to have.
What's why I love Object Pascal/Delphi - good balance between abstraction and the underlying system, compile to native code, with an clean, easy language syntax: