It's a fantastic write up on not just how system calls work, but the motivation behind why operating systems even implement them in the first place. It's not specifically about Linux, but the book is clearly heavily inspired by early *nix designs and it's still applicable.
You can read it for free here: https://pages.cs.wisc.edu/~remzi/OSTEP/cpu-mechanisms.pdf
https://www.matheusmoreira.com/articles/linux-system-calls
LWN has the kernel's perspective well covered by their articles on the anatomy of Linux system calls:
https://lwn.net/Articles/604287/
https://lwn.net/Articles/604515/
https://lwn.net/Articles/604406/
They are thoroughly dissected in these articles. I also use them as a reference.
> One big reason for this is that some system calls have additional code that runs in glibc before or after the system call runs.
That's not really the fault of the system calls. The problem is the C library itself. It's too stateful, it's full of global data and action at a distance. If you use certain system calls, you invalidate its countless assumptions and invariants, essentially pulling the rug from under it.
I've found programming in freestanding C with Linux system calls and no libc to be a very rewarding experience. Getting rid of libc and its legacy vastly improves C as a language. The Linux system call interface is quite clean. Don't even have to deal with the nonsense that is the errno variable.
Yes, everybody knows you can get from A to B on foot. But for multiple reasons, and over and extended period of time, we developed other methods of doing so. That doesn't invalidate the experience of doing it on foot, but it does make the walk into a very conscious choice that probably isn't the one most people are going to make most of the time.
libc wraps system calls. If you use libc and try to make your own system calls, you're going to collide with internal details of libc.
Not using libc is fine. Not making your own system calls via asm is fine. Pick one.
It's not! I wrote somewhat at length about that very question in this article:
It's the policy of (some/most/all) libc implementations. Don't like it? Find a different libc or do without libc.
> I have altered the ABI. Pray I do not alter it any further.
Linux is actually the odd one. It's the only one with a stable language-agnostic system call ABI. It's stable because breaking the ABI makes Linus Torvalds send out extremely angry emails to the people involved until they fix it. Because of this stability, you actually can have alternative libc implementations like musl and you can also rewrite literally everything in Rust or Lisp if you want. Only on Linux can you do this.
For some reason people try extra hard to make it look like glibc is some integral part of the kernel. Diagrams on Wikipedia showing glibc enveloping the kernel like it's some outer component. Look up Linux manuals and you somehow get glibc manuals instead. The truth is they're completely independent projects. The GNU developers have zero power to force anyone to use glibc on Linux. You can make a freestanding application using system calls directly and literally boot Linux into it. I have made it my goal to create an entire programming language and ecosystem centered around that exact concept.
This is demonstrated by the rest of your comment, in which you note that linux has a stable, language agnostic system call ABI, and that other libc implementations exist.
TFA was ONLY about Linux syscalls, so what other platforms do or do not is irrelevant in context.
Do they apply to all possible uses of syscalls? They do not.