But, anyways, not like it matters that much but still.
400 distinct syscalls is a very large number of syscalls if you generally presume they're entirely distinct.
Nonetheless, about one third of those syscalls are obsolete (being replaced by newer improved syscalls), even if a large number of programs are still using them, and about one other third of them are rarely used in the environments familiar to most Linux users, like personal computers and small servers.
The obsolete syscalls inflate a lot the number of Linux syscalls, because there are a lot of syscalls that were originally defined with an inadequate set of parameters, then they were fixed by adding parameters or changing the meaning of the existing parameters. There are many syscalls were even 3 or 4 attempts were needed until reaching an acceptable definition for their parameters.
New programs should use only the newest improved syscalls, but the documentation of the Linux syscalls in various places is usually not up-to-date itself, so a lot of people are still using older syscalls, without being aware that they are suboptimal. So the obsolete syscalls will have to be supported forever by the Linux kernels (though in most cases when an obsolete syscall is invoked it just fills the parameters with adjusted values and then it jumps to the current syscall).
It's not some Linux specific issue either. FreeBSD has three versions of statfs/fstatsfs/truncate/ftruncate.
A lot of the file related syscalls also have a XXXXat (ex: open/openat) variant taking a directory reference instead of using cwd.
Trying to counter a logical argument with a technical argument is pretty lame and doesn't make for a healthy conversation.
If you're interested in why I think what I think — there's a sibling comment where I tried to articulate my position. I'd like to hear about yours, if you don't mind.
P.S. You didn't actually offer any argument, logical (?) or technical (?!), in your original comment, and I think you're actually have the meaning of those words reversed: "logical argument" appeals to logical relations between the abstract concepts, while "technical argument" appeals to the underlying technology (the kernel implementation in our case) and tries to deal with particularities of reality. So if anything, my argument was the logical (semantical?) one, not that it really matters.
And they wouldn't ever count as distinct syscalls.
According to whom, exactly?
If a syscall is designed to counter the flaws have been observed in another syscall, then there's no way this is a distinct syscall.
If a syscall is designed to add feature to an another syscall, then there's no way this is distinct syscall.
And so on and so forth.
If you actually look at Linux kernel code, you will quickly note that a lot of these related syscall even happen to share a large amount of implementation code.
So, yeah
> 400 distinct syscalls is a very large number of syscalls
Compared to what?
It seems windows has 2000+ syscalls all combined (nt+win32).
For just ntos there are 490.https://github.com/hfiref0x/SyscallTables
https://github.com/j00ru/windows-syscalls
And does the number matter? Why can't it be 1000, 2000, 4000. In my opinion the interface is free to be defined as long as it is documented properly.
And how do you even compare how the distinct the syscalls are (e.g., pipe() and open() are about 70% similar)? And after that, what do you do with this metrics? How do you sum it up? Again, pipe() and open() are 70% similar — does that mean we have 1.3 syscalls instead of 2?
These 2 syscalls have a history typical for Linux syscalls, where frequently new syscall variants make completely obsolete their predecessors, but the old syscalls must still remain supported forever by the newer Linux kernels, to allow running legacy programs.
"pipe" has been obsoleted by "pipe2" (on 2008-10-09), which in turn has been obsoleted by "IORING_OP_PIPE".
"open" has been obsoleted by "openat", which in turn has been obsoleted by "IORING_OP_OPENAT".
Most users do not invoke Linux syscalls directly, but they use the standard C library, which has frequently shielded the end user from the evolution of the Linux syscalls. For instance, you might use the functions "open()" and "pipe()" in your C program, but the C library might invoke instead of those the more modern syscalls "openat" and "pipe2", after adjusting their parameters.
Or, you know, we can instead not engage in this subjective quagmire and look at the actual, factual number that undeniably exists. It may not be very useful for any practical purpose except for pointless dick-measuring between OSes with radically different APIs and internal architectures — but neither is this trying to measure syscall similarity, really.
Moreover, for a large number of traditional Linux syscalls (including the many variants of read/write/send/recv) there are now better alternatives that are invoked as subcommands of a single syscall: io_uring_enter.
However, I am bit skeptical as to whether io-uring will ever support all Linux syscalls.
At this point I am convinced that io-uring primarily supports I/O API / syscalls. That would mean syscalls relating to disk and network I/O. While this covers a lot of syscalls it most definitely doesn't cover all.
Though, to give some credit her, it does also cover to syscalls relating to kernel features like futex but yeah, for the most part it doesn't cover much that doesn't have to do with I/O.
Which is obviously not a problem but raises the question of whether it ever will support other kernel features.
Many of the most important syscalls belong to this class, but most of them already have io_uring alternatives. Many other syscalls are not of this kind, so for them there is no reason to replace the traditional syscall interface.
For the syscalls appropriate for io_uring the essential characteristic is that their completions can occur in a different order than the submissions of their requests, which is why all previous methods of handling them were inefficient, because they required the user program to waste time with superfluous activities, instead of just picking the completion messages from a queue.
Where this out-of-order execution is not needed, invoking the syscalls in the same way as you invoke any user function is fine.
The initial implementation of io_uring lacked the alternatives for many important syscalls, but since then most of the holes have been filled.
Besides more obvious syscalls of the read/write type, which are used for files accessed in the classic way, in order to reach maximum performance with memory-mapped files the old "madvise" syscall must be replaced with IORING_OP_MADVISE, used with Linux-specific advices (MADV_COLD, MADV_PAGEOUT, MADV_POPULATE_READ, MADV_POPULATE_WRITE).