Part of the OSTEP notes
Virtualizing the CPU means more than one thing can run on it. We need some notion of “a thing which can run on the CPU for a little while”. And we want a process scheduler, which can allow each process to have its turn on the CPU.
You need some operating system-level API to spawn and delete processes, check the current status (running? stopped? waiting on something?), maybe ask to pause or resume it or change its importance.
Programs exist as files on the hard drive. The CPU runs instructions from memory. The hard drive is not memory.
So of course, starting a program requires copying its code from the hard drive and dumping it somewhere in memory. Programs also require data
There’s lots of subtopics to drill into. An example: it would be silly if a program that required 20mb of scratch memory needed 20mb of blank space in the file. So there are ways to tell the loader “allocate X amount of memory for me and fill it with zeroes” without literally including a template for that memory in the file.
fork
Linux has a very silly way to make processes. If you call
fork
the OS more-or-less copies and pastes your process
control block into a new process.
That’s why fork
“returns twice” - from the original
process, fork
returns just like any other function call,
and in the copied process, execution begins in the middle of
fork
, and the first thing the new process does is
return from fork
.
In the main process fork
returns with the pid of the
new, child process. The child process returns with 0
(if it
wants to know the pid of the parent, there are separate APIs for
that).
There’s wait
, which waits for a process to stop, and
exec
, which replaces the current process with another one
(it invokes the loader).
Yes fork
and exec
are weird; you can’t just
ask the OS to come up with a new process for you. Say you’re a desktop
and you want to start a program. First you fork
the desktop
process, then in the fork you exec
the program you want to
run.
The trick is that exec
doesn’t overwrite
everything, so between calling fork
and
exec
you have the opportunity to configure the child
process (environment variables, where stdin and stdout are wired…).
Critically, you configure the child process the same way you’d configure
your own process – you are about to become the child process,
after all – and so they didn’t need to pack a bunch of configuration
options into exec
itself.
Compare the Windows API which packs a bunch of settings into
CreateProcessW
, and allows you to create already-suspended
processes if you want to configure even more settings about them before
they run. Nothing wrong with the Windows approach, it’s just a different
one!
Then there’s signals, process groups, owning users…