You can only do that, when you compile for a specific machine. In general you are compiling for some abstract notion of an OS. JITs always compile for the machine they are running on, so they don't have that problem. There is code, that is compiled directly to your syscalls specific to your machine, so that abstract code can use this. It's called libc for the C language.
> One of the most annoying things in the Linux manuals is they conflate the glibc wrappers with the actual system calls in Linux. The C library does a lot more than just wrap these things, they dynamically choose the best variants and even implement cancellation/interruption mechanisms. Separating the Linux behavior from libc behavior can be difficult, and in my experience requires reading kernel source code.
In my experience there are often detailed explanation in the notes section. From readv(2):
NOTES
POSIX.1 allows an implementation to place a limit on the number of
items that can be passed in iov. An implementation can advertise its
limit by defining IOV_MAX in <limits.h> or at run time via the return
value from sysconf(_SC_IOV_MAX). On modern Linux systems, the limit is
1024. Back in Linux 2.0 days, this limit was 16.
C library/kernel differences
The raw preadv() and pwritev() system calls have call signatures that
differ slightly from that of the corresponding GNU C library wrapper
functions shown in the SYNOPSIS. The final argument, offset, is un‐
packed by the wrapper functions into two arguments in the system calls:
unsigned long pos_l, unsigned long pos
These arguments contain, respectively, the low order and high order 32
bits of offset.
Historical C library/kernel differences
To deal with the fact that IOV_MAX was so low on early versions of
Linux, the glibc wrapper functions for readv() and writev() did some
extra work if they detected that the underlying kernel system call
failed because this limit was exceeded. In the case of readv(), the
wrapper function allocated a temporary buffer large enough for all of
the items specified by iov, passed that buffer in a call to read(2),
copied data from the buffer to the locations specified by the iov_base
fields of the elements of iov, and then freed the buffer. The wrapper
function for writev() performed the analogous task using a temporary
buffer and a call to write(2).
The need for this extra effort in the glibc wrapper functions went away
with Linux 2.2 and later. However, glibc continued to provide this be‐
havior until version 2.10. Starting with glibc version 2.9, the wrap‐
per functions provide this behavior only if the library detects that
the system is running a Linux kernel older than version 2.6.18 (an ar‐
bitrarily selected kernel version). And since glibc 2.20 (which re‐
quires a minimum Linux kernel version of 2.6.32), the glibc wrapper
functions always just directly invoke the system calls.