PROCESSES IN LINUX
. Process priority, amount of CPU time con-
sumed recently, amount of time spent sleeping recently. Together,
these are used to determine which process to run next.
. Pointers to the text, data, and stack segments, or
page tables. If the text segment is shared, the text pointer points to the
shared text table. When the process is not in memory, information
about how to find its parts on disk is here too.
. Masks showing which signals are being ignored, which are
being caught, which are being temporarily blocked, and which are in
the process of being delivered.
. When a trap to the kernel occurs, the machine
registers (including the floating-point ones, if used) are saved here.
System call state
. Information about the current system call, includ-
ing the parameters, and results.
File descriptor table
. When a system call involving a file descriptor
is invoked, the file descriptor is used as an index into this table to
locate the in-core data structure (i-node) corresponding to this file.
. Pointer to a table that keeps track of the user and system
CPU time used by the process. Some systems also maintain limits
here on the amount of CPU time a process may use, the maximum
size of its stack, the number of page frames it may consume, and
. A fixed stack for use by the kernel part of the process.
. Current process state, event being waited for, if any,
time until alarm clock goes off, PID, PID of the parent process, and
user and group identification.
Keeping this information in mind, it is now easy to explain how processes are
created in Linux. The mechanism for creating a new process is actually fairly
straightforward. A new process descriptor and user area are created for the child
process and filled in largely from the parent. The child is given a PID, its memory
map is set up, and it is given shared access to its parent’s files. Then its registers
are set up and it is ready to run.
system call is executed, the calling process traps to the kernel and
creates a task structure and few other accompanying data structures, such as the
kernel-mode stack and a
structure. This structure is allocated at a fixed
offset from the process’ end-of-stack, and contains few process parameters, along
CASE STUDY 1: UNIX, LINUX, AND ANDROID
with the address of the process descriptor.
By storing the process descriptor’s ad-
dress at a fixed location, Linux needs only few efficient operations to locate the
task structure for a running process.
The majority of the process-descriptor contents are filled out based on the par-
ent’s descriptor values. Linux then looks for an available PID, that is, not one cur-
rently in use by any process, and updates the PID hash-table entry to point to the
new task structure. In case of collisions in the hash table, process descriptors may
be chained. It also sets the fields in the
to point to the corresponding
previous/next process on the task array.
In principle, it should now allocate memory for the child’s data and stack seg-
ments, and to make exact copies of the parent’s segments, since the semantics of
say that no memory is shared between parent and child. The text segment may
be either copied or shared since it is read only.
At this point, the child is ready to
However, copying memory is expensive, so all modern Linux systems cheat.
They give the child its own page tables, but have them point to the parent’s pages,
only marked read only. Whenever either process (the child or the parent) tries to
write on a page, it gets a protection fault. The kernel sees this and then allocates a
new copy of the page to the faulting process and marks it read/write.
In this way,
only pages that are actually written have to be copied. This mechanism is called
copy on write
It has the additional benefit of not requiring two copies of the pro-
gram in memory, thus saving RAM.
After the child process starts running, the code running there (a copy of the
shell in our example) does an
system call giving the command name as a pa-
rameter. The kernel now finds and verifies the executable file, copies the arguments
and environment strings to the kernel, and releases the old address space and its
Now the new address space must be created and filled in.
If the system sup-
ports mapped files, as Linux and virtually all other UNIX-based systems do, the
new page tables are set up to indicate that no pages are in memory, except perhaps
one stack page, but that the address space is backed by the executable file on disk.
When the new process starts running, it will immediately get a page fault, which
will cause the first page of code to be paged in from the executable file. In this
way, nothing has to be loaded in advance, so programs can start quickly and fault
in just those pages they need and no more.
(This strategy is really just demand
paging in its most pure form, as we discussed in Chap. 3.)
Finally, the arguments
and environment strings are copied to the new stack, the signals are reset, and the
registers are initialized to all zeros.
At this point, the new command can start run-
Figure 10-8 illustrates the steps described above through the following ex-
ample: A user types a command,
, on the terminal, the shell creates a new process
by forking off a clone of itself. The new shell then calls
to overlay its memory
with the contents of the executable file