Linux启动过程初步分析

发表于2017-08-28 11:41  |  次阅读  |  0条评论  |   作者:siru90

      从启动计算机电源到进入我们熟习的Linux Shell交互界面,系统做了哪些工作?我们可以如何设置系统的启动选项,并让计算机在启动过程中完成我们指定的工作?本文将从系统启动的8个阶段做初步分析。文中错误和不足之处,请各位大牛不吝赐教。
 
一、 引导前期
目前绝大多数计算机都是冯诺伊曼体系,因此计算机的第一步便是从指令开始的。引导前期就是存储在主板上的固件的执行的过程。
在I386 CPU架构平台,这种固件叫做BIOS;目前已分支出很多版本。在Alpha CPU架构平台,这种固件有SRM和ARC两大类。由于我们接触到的计算机基本上是I386 CPU架构的,因此下面只讨论BIOS的执行过程。
BIOS实现硬件的初始化,以及启动介质的查找。BIOS程序存储在主板ROM中,其执行过程如下:
关于CPU是如何执行ROM中的代码的,可以参考陈英豪(中科院计算所)的《CPU执行第一条指令时情形》。特别的,对于多核CPU,多个核之间的同步和调度是由OS实现的;也就是说,在OS启动之前,只有主CPU的主核在运行。
1、POST(Power On Self Test,上电自检)程序
检测CPU各寄存器、计时芯片、中断芯片、DMA控制器等
2、硬件初始化和中断向量表初始化
从CMOS RAM中读取硬件配置,并对硬件进行初始化;在内存的0x0000~0x0400地址段初始化中断向量表,并初始化中断服务例程。
3、Setup程序
由于CMOS是可读写的,提供一个接口给用户配置系统硬件设置;用户说修改的配置保存在CMOS中,断点不消失。
4、自举过程
将CMOS中配置的启动顺序作为参数,从初始化好的中断向量表中找到19号中断服务例程。其主要功能为读取操作系统启动块,将其读入到内存0000:7C00h,并跳转至此处执行。
 
二、 引导过程
对于硬盘启动,BIOS会从硬盘的0头0道1扇区(即MBR)复制512B内容至0000:7C00h,并跳转至此处执行。I386平台几种常见的引导程序包括:LOADLIN,GRUB和LILO;其中GRUB最为常用。下面介绍GRUB引导程序。
MBR具有512B大小,除去66B的硬盘分区表信息,实际上只有446字节的可用空间。如此小的空间肯定不足以存放GRUB的所有代码,因此GRUB可以分为两个阶段,stage1和stage2。
Stage1:stage1(对应/stage1/start.S代码)将硬盘0头0道2扇区读入内存;执行该代码(对应/stage2/start.S代码)。该代码有两种模式:1,从0头0道3扇区读取stage1_5并执行;stage1_5具有文件系统识别功能,通过文件系统功能,加载/boot/grub/stage2并执行。2,从硬盘指定地址,直接读取stage2并执行,具有文件系统识别能力。
Stage2:stage2提供GRUB Shell环境。可以通过人机交互输入GRUB Shell命令,引导指定系统;GRUB还会默认通过读取配置文件(/boot/grub/menu.lst)提供几种系统选择。
对于SUSE Linux,在menu.lst中的配置是:
###Don't change this comment - YaST2 identifier: Original name: failsafe###
title Failsafe -- SUSE Linux Enterprise Server 10
    root (hd0,1)
    kernel /boot/vmlinuz root=/dev/sda2 vga=normal showopts ide=nodma apm=off acpi=off noresume nosmp noapic maxcpus=0 edd=off 3
initrd /boot/initrd
该脚本的意思是:系统存放在第0块硬盘(hd0)的1号分区。Kernel文件是/boot/vmlinuz,initrd文件是/boot/initrd。于是GRUB程序将kernel文件载入内存,并交控制权交给kernel程序。

三、Kernel和start_kernel过程
Kernel和initrd的关系是:kernel程序中包含系统必须的设备驱动程序;initrd存放其它设备驱动程序模块。
Linux Kernel启动之后,便开始有系统启动日志,日志存放在( /var/log/boot.msg )文件中。通过分析SUSE Linux Enterprise Server 10的启动日志文件可以总结出该系统启动过程如下:
1、读取 /boot/system.map-VERSION-0.8-smp文件,该文件指定Kernel各程序段的位置(类似于中断向量表),以及要从initrd中载入那些设备初始化程序并运行。
2、 Kernel根据配置,完成设备的检测。包括内存检测:DMA zone,Normal zone,HighMen zone。根据ACPI检测APIC等。
3、Start_kernel过程
 
Start_kernel过程
创建Dentry cache hash table,Inode-cache hash table,GDT等系统重要结构。检查CPU核心数,并初始化每个核。
调用init()函数,创建第一个核心线程。

四、Init函数
init函数完成如下工作:
创建bdflush,kupdate,kswapd等核心线程。
总线,网络,外围设备,文件系统初始化。
以只读方式装载root文件系统
从文件系统寻找init程序,并调用execve()执行该程序

五、  Init进程
在执行execve调用后,此时系统已形成一个完整的进程结构,即1号进程。Init程序执行过程为:
配置selinux
设置系统时钟
读取内核参数(/etc/syctl.conf)
配置hostname
启用swap分区
二次挂载(以读写方式)root文件系统
激活RAID和LVM设备
挂载其它文件系统
读取/etc/inittab文件,并确定系统运行级别
 
//此过程设计两个系统文件:/etc/stsctl.conf和/etc/init.d/boot.local
//其中conf是系统配置信息
//boot.local是可执行脚本,可以在此文件中加入想要开机启动的程序

六、RC过程
Inittab文件引导系统进入哪一个运行级别,并且通过:
Ln:n:wait:/etc/rc.d/rc n方式指定调用以运行界别n为参数执行rc脚本。rc脚本的执行过程是:
启动总线管理,日志管理,外围设备等常驻进程。
启用网络
执行/etc/rc.d/rcn.d目录下的所有脚本。
//如果要执行的程序需要视运行级别而定,可以在rc脚本中加入,也可以将脚本文件单独放入rcn.d中
 
七、Login
RC过程结束后,返回init程序。
Init程序此时输出登录界面及提示,接受用户名的输入,Init程序以用户名为参数,启动Login程序。
Login程序进行密码校验和root安全性控制;校验通过之后:在设置好shell的uid、gid,以及TERM,PATH 等环境变量以后,进程加载shell。

八、Shell
如果是bash,其按顺序执行如下操作:
1、执行/etc/profile
2、按顺序查找~/.bash_profile--->~/.bash_login--->~/.profile文件;一旦找到任何一个文件便结束,并执行该文件。
3、执行/etc/bashrc和~/.bashrc文件
4、输出我们熟习的Shell交互界面。
//以上n个文件在用户登录的时候,都会执行,因此可以在上述任何一个文件中加入我们需要预先执行的程序和设置的变量。
 
//另外,三条配置完美解决vim字符编码问题。
//配置~/.vimrc文件
set fileencodings=utf-8,gbk
//文件编码,vim每打开一个文件,按上述顺序匹配文件编码方式。既如果某个文件是否完全符合utf-8,如果是则认为该文件是utf-8编码的;否则,匹配gbk。
因此,需要将最难匹配的编码放在最前面。
set encoding=utf-8
//内部编码。vim打开文件之后,会将文件从文件编码转为内部编码保存在内存中;程序运行期间,所有增删和修改,都以此编码方式操作内存中的数据;程序运行结束,将内存中的数据从内部编码转为文件编码并保存为文件。
因此,需要将内部编码,方式设置为字符集最大的编码方式。
set termencoding=gbk
//显示编码,在vim需要将内存数据显示出来的时候,vim将内存中的数据从内存转换为显示编码并显示出来。
因此,显示编码应该设置为系统环境的编码方式。
本站关键字:sunny90 web开发 数据库 移动开发 服务器 Nginx Mysql PHP
Copyright © sunny90版权所有 power by sunny90.com  
湘ICP备14012284号-1,粤公网安备 44030602000307号