The manpage for _syscall(2) states:
Starting with kernel 2.6.18, the _syscall macros have been removed from the header files provided in user space. Use syscall (2) instead. (Some architectures, in particular ia64, never provided _syscall macros; syscall (2) was always required on these architectures.)
Thus, your desired approach may not work on more modern kernels. (You can clearly see that if you run the preprocessor in your code, it will not solve the _syscall0 macro) Use syscall :
Here is a usage example given in syscall(2) :
#define _GNU_SOURCE #include <unistd.h> #include <sys/syscall.h> #include <sys/types.h> int main(int argc, char *argv[]) { pid_t tid; tid = syscall(SYS_gettid); }
Since you asked for a direct way to invoke the Linux kernel without any shells for user space, I will show you examples for the 80386 and amd64 architectures.
First, you need to get the system call number from the table, for example this one . In the case of getpid the system call number is 39 for amd64 and 20 for 80386. Then we create a function that calls the system for us. On the 80386 processor, you use interrupt 128 to call the system, on amd64 we use the special syscall instruction. The system call number goes into the eax register, the output is also written to this register. To make the program easier, we write it in the assembly. Subsequently, you can use strace to verify proper operation.
This is the code for 80386. It should return the low byte of its pid as the exit status.
.global _start _start: mov $20,%eax
Build with:
as -m32 -o 80386.o 80386.s ld -m elf_i386 -o 80386 80386.o
This is the same code for amd64:
.global _start _start: mov $39,%eax
Build with:
as -o amd64.o amd64.s ld -o amd64 amd64.o