5 ms·
The article states that operating system "offer a C interface"; that's not really true of Linux, at least. It provide a series of system calls on which a C API
by alexchamberlain 6y ago
The article states that operating system "offer a C interface"; that's not really true of Linux, at least. It provide a series of system calls on which a C API is built. It's a subtle difference, but am important one if you're going to provide a runtime system abstraction.
- samatman 6y agoCan you elaborate on the difference you're pointing to here? I'm seeing a distinction without a difference, but clearly you aren't.
- wwright 6y agoYou can't write code that expects to call C functions to interop with the Linux system interface. You have to call the syscalls directly without a C-like ABI. There is some functionality you can access from glibc at link time, but not all of it (as some are implemented as macros). Even then, that's glibc providing the interface, not Linux. As the other commenter said, this is subtle (and probably non-consequential) for most people, but if you are writing an abstraction over the system interfaces, it becomes very significant to your codebase. As an example, you can lookup how Go does syscalls on Linux. It has some important consequences for their low-level design decisions: https://utcc.utoronto.ca/~cks/space/blog/programming/GoSchedulerAndSyscalls https://utcc.utoronto.ca/~cks/space/blog/programming/GoSched...
- wahern 6y agoOTOH, Linux's setuid and similar interfaces are per-thread, not per-process as required by POSIX and as what most people would expect--particularly in the context of software security. glibc and musl have to emulate the POSIX behavior, and doing it correctly is extremely tricky. See https://ewontfix.com/17/ https://ewontfix.com/17/ Linux's various APIs used for container frameworks also tend to be per-thread, not per-process; that can be both useful and a giant headache, depending on context. It's somewhat ironic that Go was used for Docker as Go is pretty much the worst possible language you could choose in this regard. Go deliberately and thoroughly obscures native thread and process semantics. IIRC, Docker was already well along and established before Go even introduced an API for pinning a goroutine to a machine (kernel) thread. I once ran across a comment where the author of (I think) runc lamented his choice of Go. But I haven't been able to find it again, so it's entirely possible it's a misattribution on my part.
- snuxoll 6y agoOn many POSIX compliant systems the stable interface to the system is libc, with syscalls being unstable and changing between releases. Linux itself does not provide a libc or other similar system library implementation (even NT has ntdll as the stable syscall layer), and it’s the syscall numbers and parameters themselves that are the stable interface.
- alexchamberlain 6y agoI guess I just meant that you don't have to code against a C ABI to make system calls: it may be more efficient to do the grunt work around the system call in the "local" language and only make the system call at the end.
- msla 6y agoIt's a bit more complicated than some of the other posters are making it seem: https://utcc.utoronto.ca/~cks/space/blog/unix/UnixAPIAndCRuntime https://utcc.utoronto.ca/~cks/space/blog/unix/UnixAPIAndCRun... > A few Unixes explicitly say that the standard C library is the stable API and point of interface with the system; one example is Solaris (and now Illumos). Although they don't casually change the low level system call implementation, as far as I know Illumos officially reserves the right to change all of their actual system calls around, breaking any user space code that isn't dynamically linked to libc. If your code breaks, it's your fault; Illumos told you that dynamic linking to libc is the official API. > Other Unixes simply do this tacitly and by accretion. For example, on any Unix using nsswitch.conf, it's very difficult to always get the same results for operations like getaddrinfo() without going through the standard C library, because these may use arbitrary and strange dynamically loaded modules that are accessed through libc and require various random libc APIs to work. This points out one of the problems here; once you start (indirectly) calling random bits of the libc API, they may quite reasonably make assumptions about the runtime environment that they're operating in. How to set up a limited standard C library runtime environment is generally not documented; instead the official view is generally 'let the standard C library runtime code start your main() function'. The kernel's API (which isn't C, but assembly language, as it relies on special opcodes) might be guaranteed stable, as it is in Linux, but even so there are or might be reasons you should call into libc anyway, and take advantage of the official functionality there.
- samatman 6y agoThank you, they were all good answers, but this one gets at why I was confused on the matter.
- floatboth 6y agoNot only take advantage of functionality, but also: - make porting to new architectures easier (have you tried writing syscalls wrappers in e.g. golang's insane assembly syntax? Not a fun time); - not break anyone's fucking LD_PRELOAD hooks!!
- jmull 6y ago> It provide a series of system calls on which a C API is built. I can't see how that isn't offering a C interface.
- alexchamberlain 6y agoAs one of the cousin comments said, on Linux the syscall table is defined as stable and various POSIX(-like) C APIs (glibc for example) are built on top.
- jmull 6y ago... thus glibc is one of the C interfaces to which the article refers! I guess I should just stop since you're making a distinction I just am not getting. I realize glibc doesn't == syscalls, but I don't see how that's relevant to the article.
- alexchamberlain 6y agoTo be really pedantic, the pure Linux OS doesn't provide the C interface - a layer on top does.
- mhh__ 6y agoOne thing not mentioned by others so far is that not all system calls available on Linux are actually available in (say) glibc, for example if you want to access the perf_event subsystem you'll have to write your own C function to handle it (This is not true for eBPF IIRC).
- creata 6y agoI think that's fair to say for Linux, since it aims for syscall compatibility, but I don't think that's true for Windows or macOS, where (unless I'm mistaken) your only options are to use libc (or an equivalent) or to constantly track breaking changes to the syscall interface.
- sedatk 6y agoI don’t recall any breaking changes on Windows syscall interface, can you give an example?
- JeanSebTr 6y agoYou don't do direct syscall on Windows, you make those through system DLLs.
- sedatk 6y agoThere is nothing preventing you from doing that though, that’s why I was curious.
- floatboth 6y agoHopefully your brain will prevent you from doing that. When OS developers say that the C library is the public interface and syscalls are private, you listen and use the C library. Golang authors completely ignored FreeBSD's policy and went with syscalls directly because "they don't change in practice" and that is infuriating. Porting to new architectures is much harder, for one.
- moonchild 6y agoWindows syscall interface changes all the time. [1] has a table of windows syscall numbers. Just looking at the first syscall, NtAcceptConnectPort, you can see that all windowses up to and including 7 used 0x60; windows 8 changed to 0x61; 8.1 changed it to 1; and then 10 changed it to 2. 1. https://j00ru.vexillium.org/syscalls/nt/64/ https://j00ru.vexillium.org/syscalls/nt/64/
- trasz 6y agoThe C API for syscalls is mostly (almost entirely) just thin, 1:1 wrappers around the system calls themselves. In FreeBSD most of it is automatically generated from the same sys/kern/syscalls.master file that is used to generate the kernel syscall table.
- moonchild 6y agoIf you're going to be so pedantic as to say that linux doesn't offer a C interface, then you also have to acknowledge that linux is not an operating system. If linux is not an operating system, what is? Gnu/linux is a very popular operating system offering a c interface, as is android linux. I do not know of any linuxoid operating systems not offering a c interface.