3 ms·
> Bullshit. A stable syscall api reflects a well designed kernel interface. Says who? I certainly wouldn't consider Linux's syscall ABI to be well designed. Yo
by nanolith 3y ago
> Bullshit. A stable syscall api reflects a well designed kernel interface.
Says who? I certainly wouldn't consider Linux's syscall ABI to be well designed. You know what is well designed? A stable facade that provides minimal overhead between two components, which prevents tight coupling. Like libc.
> You can obviously extend on it and deprecate at your will.
Only by breaking userland, which grinds this process to a crawl, even when it can happen at all. libc provides a better interface here.
> Thing is, call gates are quite more common now
I fail to see the relevance here. The mechanism by which syscalls are made doesn't make it cheaper to ossify your syscall ABI, nor does it improve security. It can certainly reduce the performance hit of a context switch. But, even with call gates, the overhead of a context switch is so high that adding the overhead of calling a wrapped function in libc is hardly going to matter.
> and there is quite some effort into of runtime linking vs static linking
What effort? Yeah, you have ld.so doing the relocation for you at runtime, but this happens once at program load time. Compared to everything else that must occur to load a program, dynamic linking adds minimal overhead.
> In my opinion, libc should not be a broker for privileged operations.
That's an interesting opinion, but beyond an unlisted "plethora of reasons", I don't see any relevant reason for this blanket ban. Having a single path into and out of the system call interface provides a way in which userland protections -- such as syscall pinning, immutable pages, etc., can be added. For defense in depth, this is useful.
> but the most obvious is that languages may not use libc in their linkage.
How does language runtime library linkage matter? What is the real difference to a language whether it calls read() or the read syscall? Either way, it has to marshal arguments through a FFI. Either way, it has to do the same amount of work. Languages must be ported to each operating system they run on. On OpenBSD and MacOS in particular, this porting means calling libc. On most OSes, libc is considered the preferred interface. On Linux, it's not, and because of that, folks assume that Linux's relative uniqueness here is somehow the default.
There is really no point to directly using syscalls. In nearly every case for unistd, socket, and fcntl, the libc wrapper is negligible. You can do all of the same things. There are few, if any, enforced C-isms. Even where they exist, they can be abstracted with a middling to average FFI library. Performance-wise, the significant overhead is making the syscall. Calling a library to do this has little measurable effect.
This is much ado about nothing.
- vacuity 3y agoI think the main concern about libc is that there are many aspects of it that aren't "minimal", so developers who want an interface for syscalls only are pressured into using libc in its entirety. I do not think libc is currently well designed either.
- nanolith 3y agoFor GNU libc, I would agree. But, not all libc implementations are equal. OpenBSD has spent a lot of time sanitizing their libc implementation, and they have even split their static C runtime library to further reduce its footprint. Developers are only really penalized for what they use. read, write, socket, bind, close, open, mmap, etc., really aren't that complex. Already, that's a significant portion of the libc footprint that any other language would use. I personally see little reason why libc couldn't be further minimized into a libunix that just contained the syscall interface. It doesn't make much of a difference really, but perhaps it would shift the largely misplaced unease that many developers have regarding anything involving C.
- vacuity 3y agoI will look into OpenBSD's implementation. Sounds interesting!
- aforwardslash 3y ago> You know what is well designed? A stable facade that provides minimal overhead between two components, which prevents tight coupling. Like libc Actually, opposed to libc. Minimal overhead means either pass by register values or using call gates to copy stack frames. Libc just adds a new layer of cruft. >Having a single path into and out of the system call interface provides a way in which userland protections -- such as syscall pinning, immutable pages, etc., can be added. None of those are libc-specific, and can also be implemented using privileged kernel implementations. So, nothing new. >How does language runtime library linkage matter? What is the real difference to a language whether it calls read() or the read syscall? Either way, it has to marshal arguments through a FFI. The level of indirection. If there is no real difference, why not use the syscall directly? Why use yet another layer of crap to - in the end - perform a call by register? > Languages must be ported to each operating system they run on. One thing us the language,another is the runtime. The runtime should be as agnostic as possible, and that actually means using syscalls, not a given libc version. > There is really no point to directly using syscalls. In nearly every case for unistd, socket, and fcntl, the libc wrapper is negligible. You can do all of the same thing. You are right, they are almost the same thing. Thats one more motive to skip libc completely, because adds little to nothing no non-c languages. > There are few, if any, enforced C-isms. Such as struct (lack of) alignment, string formats and call conventions. Few, but relevant.