Let's look at the process of booting up the machine from the time that it is switched on.
The BIOS does a Hardware Check and then proceeds to read the boot information on floppy, hard disk or CD-ROM as defined.
There are two popular boot loaders available, the first is LILO (Linux Loader) and the second is GRUB (Grand Unified Boot loader).
They are both two-stage boot loaders and will generally be installed on the small part of the hard disk that used to be called the masterboot record (MBR) in the old days.
Once the boot information is found (if found on floppy the process for loading the second boot and the kernel is slightly different) the first part of the boot loader is loaded into RAM and then it jumps into that part of RAM and proceeds' to execute the code and loads the second part of the boot loader.
A map of available operating systems is read from the disk and it is at this time that the user is presented with an opportunity to choose the operating system to use, if there is no response from the user, the boot loader will start the default operating system.
Assuming that LILO is the boot loader program that we have installed in this case, it displays Loading Linux on the screen, copies the kernel image and set-up code into memory and then starts to perform the set-up code.
Once Linux is initialized, the BIOS is no longer important to most of the rest of the boot process as Linux initializes the hardware in its own manner.
The set-up functions as an initializer of hardware and also sets up the environment so that the kernel program can execute, this includes:
Amount of RAM in the system (this it seems to get from the BIOS)
Keyboard rate and delay
Disk controller and disk parameters
Checks for a video adapter card, IBM Micro channel bus and bus mouse.
Checks that the kernel image is loaded correctly
Interrupt Descriptor Table and Global Descriptor table (Provisionally at this stage)
FPU reset (If applicable)
Maps hardware interrupts from 32 to 47 to allow for CPU exceptions
Goes to protected mode
Calls startup_32() function and then terminates
In a nutshell, this table has to store each interrupt (and exception) vector and its interrupt or exception handler. This has to happen prior to the kernel being able to enable interrupts.
80x86 processors require the use of segmentation, Linux prefers to use paging when not required to use segmentation by the architecture of the machine.
Segment Descriptors are held in one of two tables, either the GDT (defined once off) or a Local Descriptor Table (could be defined per process).
This type of exception will occur when the CPU detects an unsolvable condition when attempting to execute a command or an instruction.
|0||Divide Error /divide_error()||SIGFPE|
|1||Debug / debug()||SIGTRAP|
|2||NMI / nmi()||None|
|3||Breakpoint / int3()||SIGTRAP|
|19||...||see the section called “SIGNALS”|
Not all of the types of CPU exceptions can be fixed and the CPU will attempt to create a core dump to report the line of code where the instruction failed.
The PIC (Programmable Interrupt Controller) holds the IRQ lines or hardware interrupts from 0 to 15, which the BIOS uses. The interrupts are then mapped from 32 to 47 by the kernel because the CPU uses the other interrupts to use for exceptions. (From 0 to 19)
Although the first startup_32 function is responsible mainly for decompressing the kernel image it also sets up the segmentation registers with initial values and a provisional stack.
At this time "Uncompressing Linux" is shown on the screen Then once the decompression is complete "OK, booting the kernel" displays
The final position of the kernel in memory is then established at 0x00100000, and it is now that the second startup_32 function begins its job, which will include inter-alia:
Segmentation registers get their final values
Sets up the Kernel Mode stack for init - "init" is the father of all process and is also referred to as Process 0, or the swapper.
initializes the Page Tables
Sets bss segment of the kernel to zeros
Fills first reserved page frame with information from BIOS and operating system
Identifies the model of the CPU
(See Memory Addressing - Intel Microprocessors) There are only 6 segmentation registers, a program can re-use a register for different reasons, and in between save the context of the other reason(s) in memory restoring it to the register as needed. Three registers are reserved for, program code, program stack segment and the data segment.
Page tables are stored in memory and are there to match or to map the linear addresses to physical addresses. Prior to starting the paging unit, the kernel has to initialize the paging tables. The paging unit with an Intel processor handles 4 KB pages at a time. A page table is only used for the current virtual memory used by a process (regions).
In UNIX programming, the linear address space is usually partitioned into segments. So the bss segment is used for uninitialized variables. In other words, variables that are not set prior to the program executing, but rather set and unset during the execution of the process as it needs the variable(s). (Could also ref. Text, initialized Data, stack segments for your interest)
Startup_32() then calls the Start_kernel() function.
This section will give you ideas of where to find out information, some of the functions and tables we will cover throughout the course, but some you may have to look around more for yourself if you need the information.
The following are initialized by start_kernel():
Page Tables by paging_init()
Page Descriptors by free_area_init(), kmem_init() and mem_init()
Exception Handlers and Interrupt Vector data structures by trap_init() and IRQ_init()
Caches by kmem_cache_init() and kmem_cache_sizes_init()
System date and clock time_init()
Process 1 called by kernel_thread()
Process 1 executes /sbin/init program (see Logging in)
Many messages are displayed during this process, you would have seen that when doing your installation of the operating system in chapter two of the system administrators course.
When the system stops booting you will see the ever-familiar login prompt on your screen (unless you have started X Windows, in which case the screen will be presented in a graphical display).
Page Descriptors are generally controlled by a page hash table (index of sorts). Used when process calls long file, when lots of page descriptors are loaded into memory hard to find a specific set of data, therefore a page hash table acts as a preliminary index so that only relevant pages of the file are loaded into memory and memory not swamped with irrelevant detail.
(Ref. Slab, slab allocators, general and specific caches) kmem_cache_init() and kmem_cache_sizes_init() are used during system initialization to create the general caches. Specific caches are created by kmem_cache_creat(). Fundamentally slab allocators allow caches to be created because of the same frames of programs being run again and again and rather than reallocating memory each time for the same purpose, the kernel uses a slab allocator (memory algorithm) to store the memory areas in a cache. (most frequently used etcetera is allocated into the algorithm)
An example of a kernel thread is init or process 0. It is a system process that only ever runs in Kernel mode. Some other examples would be the buffer flusher, the swapper, network connection services (keventd, kapm, kswapd, kflushd (bdflush), kupdated, ksoftirqd). These execute single C functions as apposed to a regular process that will use User and Kernel mode and the kernel has to call any C functions used. (See system calls and traps).
The Operating System called Linux consists of multiple programs, the most important one is called "the kernel" or the core of the operating system. The operating system controls the access of the hardware and the relationships with the apps and the users.
Although some operating systems speak directly to the hardware such as DOS, the UNIX and Linux operating systems deal with the hardware through the kernel and a device driver file (discussed previously).
To control the accesses of hardware and other functionality the operating system chooses to operate in either a user-mode or the kernel-mode. We will discuss further implications of this in the section on processes.
It is said that the Linux operating system is multi-user and multi-processing, and yes a lot of users can access the system apparently all at the same time. However with just one CPU only one process can ever run at a time.
It appears multitasking because it has a method of keeping each process separate, and calculating a fair share of processing time for each process, a system whereby it is possible to monitor the use of resources at all times and to keep usage at an optimum level.
We will cover the process in much more detail after the bootup section of the course, however for our purposes at this time we need to look at a definition that can stand the test of the boot sequence.
A process can be one of two things, either the instance that a program is executed in memory OR the part (context) of the program that is currently executing in memory.
In order to maintain a smooth flow of processor / process time there is a system process available called the scheduler or "sched".
Another process that commences during the bootup sequence is the initializer or "init", as discussed previously, Process 0 the father of all other processes.