Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux system calls vs C lib functions

I have bit bit of confusion regarding these two so here are my questions;

The Linux man-pages project lists all these functions: https://www.kernel.org/doc/man-pages/

Looking at recvfrom as an example, this function exists both as a Linux system call as well as a C library function. Their documentation seems different but they are both reachable using #include <sys/socket.h>. I don't understand their difference?

I also thought systems calls are defined using hex values which can be implemented in assembly directly, their list is here: https://syscalls.kernelgrok.com/

However I cannot find recvfrom in the above link. I'm a bit confused between Linux system calls vs C lib functions at this point!

Edit: To add to the questions, alot of functions are under (3) but not (2), i.e clean. Does this mean these are done by C runtime directly without relying on system calls and the underlying OS?

like image 647
josh Avatar asked Aug 31 '19 01:08

josh


3 Answers

First, understand that that C functions and system calls are two completely different things.

System calls not wrapped in the C library must be called through the syscall function. One example of such a call is gettid.

To create a gettid system call wrapper with syscall, do this:

#define _GNU_SOURCE
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>

pid_t gettid(void)
{
    pid_t tid = (pid_t)syscall(SYS_gettid);
    return tid;
}

Here's an excerpt from the NOTES section of the man-page, which explicitly states that this function is not defined within the C library:

NOTES
Glibc does not provide a wrapper for this system call; call it using syscall(2).


recvfrom is a C library wrapper around a system call.
Everything in section (2) is a system call. Everything in section (3) is not. Everything in section (3) (with a few notable exceptions, such as getumask) has a definition in the C library. About half of everything in section (2) does not have a definition (or wrapper) within the C library (with the exception of functions mandated by POSIX, and some other extensions, which all do), as with gettid.

When calling recvfrom in C, the C library calls the kernel to do the syscall.

The syscall function is the function that puts the system call number in the %eax register and uses int $0x80.

The reason you don't see recvfrom in https://syscalls.kernelgrok.com/ is because https://syscalls.kernelgrok.com/ is very, very incomplete.

The reason there are many functions in (3) that you don't see in (2) is because many functions on (3) don't have a system call. They may or may not rely on system calls, they just don't have a system call with that specific name that backs them.

like image 146
S.S. Anne Avatar answered Oct 18 '22 12:10

S.S. Anne


exists both under the linux system call

The way userspace programs communicate with kernel is by using syscall function. All syscall() does is push some number on specific registers and then execute a special interrupt instruction. On the interrupt the execution is transferred to kernel, kernel then reads data from userspace using special registers.

Each syscall has a number and different arguments. User space programs are expected to "find out" arguments for each syscall by for example inspecting the documentation.

Linux system call is just a number, like __NR_recvfrom which is equal to 231 on x86-64 architecture.

C Lib function

A C library function is a function implemented by the C library implementation. So, for example glibc implements recvfrom as a simple wrapper around syscall(__NR_recvfrom, ...). This is C interface the library provides programmers to access kernel related functions. So C programmers wouldn't need to read the documentation for each syscall and have nice C interface to call the kernel.

However I cannot find recvfrom in the above link.

Don't use the link then. At best inspect kernel sources under uapi directory.

like image 2
KamilCuk Avatar answered Oct 18 '22 13:10

KamilCuk


First of all, functions listed in section (2) are functions. They are different from functions in section (3) in that there is always a system call behind.

Those function will usually do additional work to make them behave like POSIX functions (converting returned value to -1 and errno), or to just make them usable (clone syscall requires libc integration to be useful). Sometimes arguments are passed to a system call differently than function prototype suggests, for example they can be packed into a structure and pointer to that structure can be passed through a register.

Sometimes a new syscall is added to fix some issues of the older syscall. In this can a function can be implemented using a new syscall transparently (see mmap vs mmap2, sys_select vs sys_old_select).

As for recvfrom, socket-related functions are implemented by either their respective syscalls or by a legacy sys_socketcall. For example musl still has this code:

#ifdef SYS_socket
#define __socketcall(nm,a,b,c,d,e,f) syscall(SYS_##nm, a, b, c, d, e, f)
#define __socketcall_cp(nm,a,b,c,d,e,f) syscall_cp(SYS_##nm, a, b, c, d, e, f)
#else
#define __socketcall(nm,a,b,c,d,e,f) syscall(SYS_socketcall, __SC_##nm, \
    ((long [6]){ (long)a, (long)b, (long)c, (long)d, (long)e, (long)f }))
#define __socketcall_cp(nm,a,b,c,d,e,f) syscall_cp(SYS_socketcall, __SC_##nm, \
    ((long [6]){ (long)a, (long)b, (long)c, (long)d, (long)e, (long)f }))
#endif

which tries to use appropriate syscall if available, backing off to socketcall otherwise.

like image 2
StaceyGirl Avatar answered Oct 18 '22 12:10

StaceyGirl