So the kernel handles things like reading and writing. But it also handles things
like processes. When we start our application, it runs in a process - and the kernel
decides which process gets to run and when. It interrupts processes and resumes them,
prioritizing the important stuff - but also, giving the illusion that a single CPU core
can do multiple things at once (when it really can only do one at a time).
And in our further communication with the kernel, whenever we want to
refer to that resource, we'll just use that number.
And this answers one of the questions you might have had while following this
article: in the strace
output for most programs, we saw a call to close
(which, well, closes a file descriptor) - but in our sample C program, we
never bothered calling it!
This is because the kernel, in its infinite wisdom, keeps tracks of opened
file descriptors, and cleans them all up once the process exits.
"This is all getting a bit theoretical" whispers someone in the back. "I'm glad
he's not showing us kernel code, but.. are we just supposed to trust that the
kernel cleans up file descriptors?"
We need to clear up a potential source of confusion. We saw a read()
function
in the source code for glibc (the C library that ships with most Linux distributions),
but it is distinct from the actual read
syscall.