有时候需要了解系统启动的过程,在安装系统,自定义启动程序以及配置shell profile的时候比较有用。当然,了解这些过程,对于我们理解系统是如何工作的也是很有意义的。网上也有很多有用资料,不过有些文章太具体详细,有些只描述了某一子过程中的情况,有些描述的跟现在的有些差距。为此,加上自己的理解,稍稍汇总一下,写个简介,看起来方便,同时附上具体过程的一些链接,方便要深入的时候可以随时深入。因为现在用的系统是Opensuse13.1,所以就以此系统作为描述的对象,其实,大多数Linux系统都是差不多的,只是一些细小方面的区别。
BIOS
当计算机一开始被启动,或者重新启动时,处理器将从BIOS(Basic I/O System)开始执行。BIOS存储于主板上的闪存中,主要做什么用途呢?BIOS进行所谓的POST(Power On Self Test),然后依据设置的引导顺序从硬盘,U盘或CDROM中读入“引导块”。通常BIOS中设的引导顺序为硬盘在最前面,那么就把第一个硬盘的第0柱面,第0磁头的第1个扇区读入内存,然后跳到那里开始执行。这个扇区被叫做:MBR(Main Boot Record)。MBR
MBR的大小为512字节。其中的446字节存放boot loader,接下来的64字节存放磁盘分区表信息,最后的两个字节为MBR的终止标志位,为0xAA55。在早期没有GRUB之类的引导程序前,操作系统直接由MBR的boot loader启动,但是因为它的存储区域有限,很难做复杂的启动控制,尤其在多操作系统的情况下。所以有了引导程序,现在用的比较多的是GRUB。因为boot loader存储区域的限制,GRUB只能把一小部分hook的程序放在这里,用来跳转到GRUB主要的程序。这部分hook的程序就叫做GRUB stage1。
(在装完Linux系统后再装Windows系统,启动的时候就会直接启动Windows,就是因为MBR在安装Windows的时候被重写了,只能引导Windows。在这种情况下,有种办法是从Windows启动的时候用Grub4dos命令行模式启动到Linux系统,然后重新安装GRUB stage1到MBR)GRUB
如果有/boot分区,GRUB会被安装到此分区下,当然,这里的GRUB指GRUB stage2。GRUB从menu.list中读取配置显示到屏幕让用户选择,用户也可以通过命令行手动进行启动。一般来说有3个参数,root---用来指定哪个硬盘哪个分区,kernel---用来指定用哪个内核文件,initrd---用来指定用哪个初始化ram的img文件。有了这3个参数,就可以启动Linux系统了。
(GRUB2请参考baidu文库相关教程)
(http://blog.renren.com/share/281974470/14862436498这篇博文详细介绍了1,2,3步骤)Kernel
内核映像文件vmlinuz:包含有linux内核(vmlinux)的静态链接的使用zlib压缩过的压缩文件。传统上,vmlinux被称为可引导的内核镜像。Kernel通过调用start_kernel,会调用一系列初始化函数来设置中断,执行进一步的内存配置,并加载初始 RAM 磁盘。然后,启动 init 函数,这是第一个用户空间进程(user-space process)。最后,启动空任务,现在调度器就可以接管控制权了(在调用 cpu_idle 之后)。通过启用中断,抢占式的调度器就可以周期性地接管控制权,从而提供多任务处理能力。
(http://blog.csdn.net/zhoudaxia/article/details/6666683详细分析了内核启动过程)
(http://www.cnblogs.com/lcw/p/3337937.html详细分析了内核启动代码)Init
init即是/sbin/init,为Linux系统第一个进程,进程号为1,是系统所有进程的起点。控制系统启动的脚本放在/etc/init.d里(有的Linux系统放在/etc/rc.d里,在Opensuse13.1中,/etc/rc.d为一指向/etc/init.d的链接)。这些脚本或直接或间接地被/sbin/init调用。/sbin/init的配置由/etc/inittab提供,/etc/inittab文件的每一行包括四个域(id:runlevels:action:process)。
/sbin/init调用/etc/init.d/boot(boot level master script)来初始化系统,比如文件系统检测,同时也调用/etc/init.d/boot.d中的硬件初始化脚本,然后调用/etc/init.d/boot.local,这个脚本用来执行用户自定义的一些命令。需要注意的是,这一文件执行时网络等设备都尚未就绪,使用时应小心。
在系统进入运行级前,/sbin/init还会运行一个用户可以自定义的脚本/etc/init.d/before.local(此时网络等设备也未就绪),然后/sbin/init将根据/etc/inittab中的配置跳转到默认的run level,调用/etc/init.d/rc(run level master script)来启动或停止一些服务。
为了控制一个运行级的服务,相应的脚本被链接到run level directories /etc/init.d/rc<X>.d中,其中<X>为0,1,2,3,4,5,6,S,代表运行级。在/etc/init.d/rc<X>.d中,有以S开头的start links和以K开头的stop links,start links将在系统进入一个运行级时被依次调用,stop links将在系统退出一个运行级时被依次调用。
/etc/sysconfig下的系统配置文件用于配置那些对应的服务。在Opensuse13.1中,这些系统配置文件可以被YaST改变,或者直接拿编辑器改变,不过就是用编辑器改变后,还得运行/sbin/SuSEconfig来使这些配置在系统中生效。
系统完成运行级的启动后,/sbin/init还会运行一个用户可以自定义的脚本/etc/init.d/after.local,对于多数用户自定义的启动程序来说,将其加到/etc/init.d/after.local中较为合适。比如上文中介绍的goagent,想开机自动启动的话,在/etc/init.d/after.local中加上命令即可。TTY
运行级启动完后,将会返回到/sbin/init。这时基本系统环境已经设置好了,各种守护进程也已经启动了。/sbin/init接下来会打开终端tty,以便用户登录系统。
(http://www.jb51.net/article/3567.htm对Init及tty有比较详尽的分析)SHELL
用户登录系统后,根据/etc/passwd配置的默认shell,启动相应的shell。一般大多都是bash,这里也以bash为例描述下bash读取配置文件的过程。
/etc/profile --- ~/.inputrc(/etc/inputrc) --- /etc/profile.d/* --- /etc/profile.local --- ~/.bash_profile(~/.bash_login |~/.profile)
.bash_profile和.bash_login以及.profile只会执行其中一个。搜索顺序以 .bash_profile->.bash_login->.profile这样的顺序进行,如果有前者就不执行后者。
~/.bashrc用于子shell启动配置。
(http://blog.csdn.net/jxhnuaa/article/details/3254553有对比介绍)
到此为止,提示符开始闪烁。。。