libc as a wrapper around syscalls
/ glibc: GLIB-see /
Imagine the kernel speaks only a terse, fussy machine dialect: put exactly this number here, these values in those four registers, then fire this one instruction, and read the answer back from a register. Almost no programmer wants to write that by hand for every file they open. So there is a translator that lives in user space and speaks both languages - you call it in friendly C, and it handles the fussy machine dialect for you. That translator is the C standard library, libc.
Concretely, libc is the standard library that ships with C - it provides familiar functions like printf(), malloc(), strlen(), fopen(), and read(). Some of these are pure user-mode code that never touch the kernel at all (strlen() just walks bytes in memory). Others are thin wrappers: the libc function read() does little more than load the system-call number and arguments into the right registers, execute the trap instruction, and translate the kernel's raw result into the C convention you expect (returning the byte count, or returning minus one and setting the errno variable on failure). 'Thin wrapper' captures the idea - the wrapper adds almost nothing of its own; it mostly marshals arguments and forwards the request. Higher-level functions like printf() are thicker wrappers: they format text in user space and only then call the thin write() wrapper underneath.
Why it matters: this layering is why C programmers almost never issue raw system calls themselves. The library gives you a stable, portable, pleasant interface and hides the per-platform register and number details behind it. It also means a single printf() can become zero or many actual system calls depending on buffering, and that the same C program can be recompiled on a different OS where libc maps the same call name onto a different underlying syscall. When you understand that most of the C standard library is either pure user-mode work or a thin wrapper over a syscall, the whole interface stops being magic.
The libc read() wrapper is essentially: move the read syscall number and the three arguments into registers, execute syscall, then if the kernel returned a negative value, store its negation into errno and return minus one; otherwise return the value. That is almost the whole wrapper.
A thin wrapper marshals arguments, traps, and adapts the result to C conventions.
There is more than one libc: glibc, musl, and others all implement the same standard interface differently. 'libc' names the role (the C standard library wrapping syscalls), not a single specific file - though the C standard library and the system-call wrappers are sometimes packaged separately.