LINKS:
Project Home
Presentation (.ppt)
Presentation (.html)
Resources
Notes
IFE Diagram
Boot Process
|
The Linux Boot Process
When a computer is turned on, well before the OS (operating system) gains
control, the BIOS begins executing. The BIOS (basic input output system) is
the software stored in read-only memory which performs basic hardware tests and
configures fundamental aspects of the hardware at power up. Once these initial
steps are complete, the BIOS searches for a boot record across the available
boot devices such as hard drives, floppy drives, and CD-ROM drives. The boot
record is stored at a specific location which the BIOS author prescribed and at
which the OS author stored a small program called a boot loader. When the BIOS
finds a boot loader, it copies the program into memory and transfers execution
to the loader.
The purpose of the boot loader is to copy the kernel, the operating
system’s core, into memory. Once the kernel has been copied into memory, the
boot loader transfers execution to the kernel. The boot loader has now
completed its job.
When the Linux kernel is copied to memory, only a small part of it is in
an executable form; the majority of the kernel is stored in compressed form, in
a similar fashion to the way files are stored in a ZIP file. Thus, the first
step that the executable portion of the kernel takes is to decompress the
remainder of the kernel. Execution then jumps to the decompressed portion of
the kernel.
While storing the kernel in compressed form may seem odd, it is
justified. Memory (RAM) is much faster than storage (e.g. a hard drive).
Consequently, a smaller, compressed kernel image can be copied from storage and
uncompressed faster than a larger kernel can be copied to memory. Secondarily,
a compressed kernel takes up less space in storage, which can be an important
consideration in embedded systems and other devices with limited storage space.
The first tasks of the uncompressed kernel are to initialize low-level
aspects of the operating system. For example, one of these low-level tasks is
to initialize virtual memory by setting up page tables and, if necessary,
turning on virtual memory support in the processor. Other low-level tasks
performed by the kernel include reading parameters passed from the boot loader
to the kernel and detecting features of the host hardware.
To this point in the kernel’s execution, the source code which produced
the kernel was written in assembly language. Assembly language was used so
that hardware specific tasks could be written more easily. Finally, the
execution of the kernel has reached a point that the majority of tasks will be
performed at a higher level and will be more hardware agnostic; consequently, a
higher-level programming language can be used more productively to write the
kernel. In the Linux kernel, C is the high-level language of choice.
Initializing vectors for software and hardware interrupts is one of the
first high-level tasks performed by the Linux kernel. Interrupt vectors are
arrays of memory addresses in which each address points to a subroutine which
can handle the trap or interrupt. Software interrupts, or traps, are used, for
example, to initiate a system call, which is a function call from a user
program to a kernel function. Hardware interrupts occur, for example, when a
peripheral device needs to communicate with the processor. Other areas which
the kernel needs to initialize include the array of process structures, the
system clock timer interval, the file system, and the structures and memory
areas related to forking a process or creating a thread.
Thus far, the kernel has been the only software other than the BIOS to
use the computer’s processor or processors. However, for the computer to do
meaningful work, the kernel needs to allow other processes to run. These new
processes will then use the kernel’s system calls as a set of subroutines. At
the point other processes begin to run, the kernel runs in one of two
contexts. In one context, the kernel runs as a subroutine of a process in
response to a system call or interrupt. In this context, the kernel does not
have its own thread of execution; it simply co-opts the execution of the
process which was running when the system call or interrupt occurred. In the
other context, the kernel does have its own thread of execution; however, it
uses its execution to consume clock cycles for which no other process has use.
Thus, in this mode, the kernel is called the idle process.
So, when the kernel has nearly finished initialization, it begins
preparing for the transition described above. This transition begins with the
kernel adding an entry for itself, as the idle process, in the processes
table. Of course, the idle process is given the least possible execution
priority. Once the idle process table entry has been created, the kernel
performs its first fork to create the first non-idle process, the init
process.
After the fork, the init process will begin execution because it has
higher priority than the idle process. The init process is part of the kernel,
but it is the kernel’s last throes. Before it gets to its real task, the init process
will perform some housekeeping, such as freeing up now unnecessary kernel
initialization memory. Another such task is setting up drivers for the
computer’s hardware, which like housekeeping may sound simple, but is a great
deal of work that no one likes to talk about.
Once these preliminary tasks are complete, the init process sets to its
real task, ensuring its own destruction; it searches a number of predefined
locations in the file system for an init program which will start various other
system level programs. Once the init program has been located, it is loaded
into memory over the top of the init process and begins execution. Thus ends
the init process.
Although the init process has departed, the idle process remains. In
fact, the idle process has most likely been executing intermittently since the
forking of the init process. At moments when the init process had nothing to
do, such as while waiting for the hard drive to return a piece of data, the
idle process executed. When the idle process executes, it does as little as
possible, periodically looking for a process which is ready to run. So after
the kernel has finished the hard work of booting the computer, it settles into
the tasks of acting as a subroutine and of executing when no other process has
computation to perform.
|