For the complete documentation index, see llms.txt. This page is also available as Markdown.

From C++ to the Linux Kernel: Connecting the Layers

I’ve been learning C++, but somewhere between pointers, streams and sockets, I realised the more interesting lesson was understanding how the layers underneath Linux connect.

Consider a seemingly simple line:

int fd = socket(AF_INET, SOCK_STREAM, 0);

It looks simple:

AF_INET      -> IPv4
SOCK_STREAM  -> byte-stream socket
socket()     -> create a socket
fd           -> returned file descriptor

But what does fd actually represent?

Following the Socket

I created a socket and kept the process alive:

python3 -c 'import socket,time,os; s=socket.socket(); print("PID:",os.getpid(),flush=True); time.sleep(300)' &
PID=$!

Then inspected its file descriptors:

ls -l /proc/$PID/fd

And there it was:

0 -> /dev/pts/1
1 -> /dev/pts/1
2 -> /dev/pts/1
3 -> socket:[15292]

FD 3 is not the socket itself. It is the process’s handle to a kernel-managed socket object.

The picture starts looking like this:

Watching the Boundary

Then I ran the same experiment through strace:

The interesting part:

Now the layers connect.

strace shows the interaction with the kernel.

/proc/<PID>/fd shows the resulting process state.

Even something as ordinary as print() eventually becomes:

And suddenly pipes and redirection make more sense too.

Underneath, the shell is manipulating file descriptors and connecting processes together.

The Bigger Lesson

None of these concepts are particularly obscure individually:

The interesting part is understanding how they connect.

That is what I’m finding valuable about learning C++.

Not simply learning another programming language, but developing the ability to follow an operation through the system.

Linux starts becoming less of a collection of commands to memorize and more of a system whose behaviour you can trace, observe and reason about.

Last updated