BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / linux / #24987同步于 2007/8/17
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Linux机器人发帖

Re: 关于Linux启动过程分析

piaoice
2007/8/17镜像同步2 回复
【 在 piaoice 的大作中提到: 】 : 周五下午也没啥事,正好刚才看见有说grub相关的。把自己对Linux启动过程的理解写了个文档。其中会有很多问题,启动过程有些地方也不明确,贴出来大家多多讨论。 The Boot Process of RH Linux in X86 System (20070818 ) by Wang. 本文分析GNU/Linux系统启动过程的细节,也就是从开机(按下power键)到登录系统login这个阶段,我们的系统在启动过程中都做了什么事。其中,我们重点分析Linux启动过程中,将vmlinuz和initrd文件载入内存后,系统都做了什么事。 不同的Linux发行版,或者同一个Linux发行版,在不同的平台上,其系统启动过程会有所差别,本文以RHEL5在X86平台上的启动过程为例,分析Linux的启动过程。 首先,操作系统启动的过程,实际上可以看成是控制权移交的过程。我们先粗略的将RHEL5 在X86上启动过程分为以下5个阶段: 1、开机主板BISO自检到MBR阶段; 2、在MBR启动bootloader (grub)到 /boot将stage2载入内存阶段; 3、将vmlinuz和initrd载入内存,以及之后vmlinuz和initrd所做的相关工作; 4、启动/sbin/init进程,检查相关文件系统并挂载,以及启动相关服务操作; 5、进入login界面。 其细节如下: 阶段1:系统开机上电BIOS过程。控制权在主板BIOS。 系统Power on上电后,启动主板BIOS程序,系统将会执行POST(Power On Self Test)代码来对各设备进行检查,譬如CPU、显卡、内存、鼠标键盘等。BIOS相当于提供了一个和系统设备最底级别的接口。POST自检过程中若发现系统设备出现任何问题,会给出提示信息并鸣笛警告。 BIOS自检完成后,会启动自举程序,根绝我们在BIOS中设置的启动顺序搜索启动驱动器。比如我们的硬盘、光驱、网络服务器等。 阶段2:boot loader过程。控制权在boot loader。 Boot Loader,简单的说就是启动系统的程序,如grub, lilo,也可以将boot loader本身看成一个小系统。 如阶段1过程所述,假设系统通过硬盘引导,那么BIOS会将MBR中的内容读入内存。MBR(Mast Boot Record)是硬盘的第一个扇区,共512字节,其中包含了硬盘的分区信息以及boot loader的一部分信息。这个时候,控制权在MBR。 MBR中的信息被载入内存,系统启动的控制权移交到MBR后。系统会启动Boot Loader,在这里是grub。实际上,grub分为stage1和stage2阶段(准确的说中间还可能有stage1.5阶段)。其中,stage1是安装在MBR的二进制机器代码,它唯一的作用就是定位stage2位于硬盘上的哪个分区位置,并将其载入内存。 一般来说,stage2安装在/boot分区,一旦stage2载入内存后,就会图形化的方式将grub界面呈现给用户(这个界面大家应该常见)。 阶段3:内核引导阶段。 如阶段2所述,grub界面起来后,用户选择要启动的系统,回车,grub的控制权就到此结束,移交给所启动的系统。这里我们以交互的方式来启动系统。 在grub页面,按键盘c进入grub页面。 执行 kernel /vmlinuz-**(版本号) 这一步是将内核载入内存; 执行initrd /initrd-**.img ,这一步将initrd载入内存,关于initrd在后面会详述其细节。 执行boot 后,就启动我们所选择的系统了。 现在我们详细分析这一阶段的细节: 一旦vmlinuz载入内存,此时控制权就移交给内核。内核会立即初始化系统中各设备并做相关配置工作,其中包括CPU、I/O、存储设备等。(关于这部分工作,细节上的处理还不清楚)。之后内核会定位之前载入内存的initrd文件。 在2.6内核中,支持两种格式的initrd,一种是2.4内核的文件系统镜像 image-initrd,一种是cpio格式。我们以cpio格式为例,内核判断initrd为cpio的文件格式后,会将initrd中的内容释放到rootfs中。 插一段话,关于initrd,可以看成是一种基于内存的文件系统,启动过程中,系统在访问真正的根文件系统 / 时,会先访问initrd文件系统。我们可以将initrd中的内容打开来看,会发现有bin、devetc、lib、procsys、sysroot、init等文件(包含目录)。其中包含了一些设备的驱模拟块,比如scsi ata等设备驱动模块,同时还有几个基本的可执行程序insmod, modprobe, lvm,nash。主要目的是加载一些存储介质的驱动模块,如上面所说的scsi ideusb等设备驱动模块。然后初始化LVM。 initrd中的内容释放到rootfs中后,内核会执行其中的init文件,这里的init是一个脚本,由nash解释器执行。nash是RedHat写的一个脚本解释器,我们在系统启动过程中,也能看见这么一个标志:nash版本****。这东西的目的就是在这里去执行init文件中的内容。这个时候内核的控制权就移交给init文件处理,我们查看init文件的内容,主要也是加载各种设备驱动,主要是存储介质相关。 驱动加载后,会创建一个根设备,然后将我们实际的根文件系统 / ,以只读的方式挂载。这步结束后,会执行switchroot,转换到真正的根/上面去,同时运行/sbin/init程序。关于switchroot,这是在nash中定义的程序。 阶段4:执行/sbin/init程序后,我们的1号进程就起来了。是系统中以后各进程的祖先,进程树的根。这之后的工作,各Linux发行版的工作就类似了。主要工作就是检查文件系统并挂载,加载各项服务以及用户环境的配置等。涉及的主要文件:/etc/fstab,根据fstab文件检查文件系统,并且第二次以读写方式挂载实际的根文件系统 / ,以及挂载fstab上描述的其它文件系统。/etc/rc.sysinit, /etc/inittab, /etc/rc.d/rcX.d/... , /etc/rc.d/init.d/... ,/etc/rc.d/rc.local根绝这几个文件,确定运行级别,以及所要启动的服务,用户环境等。其细节不详述,关于这rc.sysinit这个文件也没分析过。 阶段5:上述阶段一切正常,进入login界面。 尾注:以上是对Linux启动过程所做事情的一些分析,并没有深入到代码一级的分析。其中也有一些不明确的地方。比如说内核载入内存后,关于rootfs文件系统的代码一级的操作,并不清楚,暂时也没找到在哪儿做的这个工作。 PS:鉴于对Linux认识有限,以上所述肯定会存在很多问题。在这里先免责声明哈:)
订阅后,新回复会通过你的通知中心匿名送达。
2 条回复
SC80T机器人#1 · 2007/8/17
哇 colyli大哥 呵呵 我来补充下这个第一阶段,呵呵,以前看书抄的笔记,现在直接打上来 1.按下开关,电源供电,主板向CPU发送并保持Reset信号知道稳定供电(我猜测就是指电压稳定),CPU马上从FFFF0H处开始执行指令,为跳转指令,跳到系统bios中真正的启动代码 2.POST(这是简写,是啥应该都知道吧),这里只检查640KB常规内存(接触过dos和接触过底层的都知道这东西的) 3.查找显卡BIOS,通常在C0000H处,调用,初始化显卡(有提示信息)(应该就是开机的滴声以后的那个显卡信息,就是只有显卡型号和显存大小的信息那个),接着查找其他bios,初始化(这个还有哪些有啊,不懂) 4.查找完其他bios后,系统bios显示出自己的启动画面(就是前面显卡信息显示完后的那个屏幕里面上面那部分,知道award 6.00PG XXXXXX完) 5.检测,显示CPU类型,工作频率,并测试所有的RAM(这个过程也有信息的,就是紧接上面那部分的) 6.检测一些标准硬件设备(好像就是硬盘,光驱,还有主板上面那些什么时钟啊之类的特别老的设备,新设备都不在里面),绝大多数新bios还会检测,设置内存时序,硬盘参数和访问方式 7.bios内部支持即插即用(PNP)代码检测,配置即插即用设备,显示设备名称型号,分配中断,DMA和I/O端口资源(个人认为这些就是比较新的设备了,不过比较新也是相对上面来说的,现在来看也是很标准的设备了) 8.多数清屏,并概略的列成表格,显示各种标准硬件设备,以及他们使用的资源和一些工作参数(如果是在用grub的话,就是grub加载信息上面那一屏,不过一般闪过的比较快) 9.更新ESCD(这个也是有信息提示的,就提示Updating ESCD.........),ESCD在CMOS里面 10.重硬盘,光驱,软盘启动,如果是硬盘,在bios里面已经写好了读第一个扇区(也就是MBR),通过MBR 1)grub,通过grub里面的东西来读和配置东西,有个很重要的东西grub.conf 2)是windows系列的,找到Actve partition,也就是有80的那个(呵呵,这里卖弄一下),再读取执行分区引导记录,再读取,执行IO.SYS或者NTLDR 如果热启动,post被skip,直接从第3步开始,第5部也不再执行 终于打完了……,呵呵,上面说得提示信息,发现本上面很多被hide了,台式上面是很清楚的 PS:我写的时候,ls都还没回复呢……
CNLAS机器人#2 · 2007/8/17
写的很不错啊。。。不过建议还是看看代码。。。grub这个东西我觉得是除了linuxkernel之外gnu里最值得看源代码的东西了。。。这玩意的彻底分析当毕设都够了。。。XD 那我就扫尾一下解决一些遗留问题。。。XD 以下所说的过程和代码以grub0.97版为例。。。grub2和1的启动过程有点区别。。。后面再说。。。给出的路径大部分是指源代码包的 1、BIOS启动sc80t说了。。。但是注意一点BIOS是参与内存编址的。。。所以不存在读入物理内存这个概念 2、BIOS将0头0道1扇区也就是MBR读入内存地址0x7c00处。。。然后检查0x7dfe是否等于0xaa55(WORD)确认是有效MBR后开始执行 3、Grub安装好后0头0道1扇区就是stage1(/stage1/stage1.s)。。。其实stage1的任务非常的单纯。。。去读取0头0道2扇区然后闪人。。。XD 0头0道2扇区的内容就是源代码里\stage2\start.s编译后也是一个512字节。。。stage1将start.s读入内存地址0x8000然后跳过去执行 4、start.s就是stage1.5 or stage2的入口。。。一般情况下stage2还是放在需要具体的文件系统下的。。。这个时候需要读取stage1.5。。。但是注意。。。这里的stage1.5不是/boot目录下的那些文件。。。你都能读取/boot目录了还要stage1.5干嘛。。。 所以这里的stage1.5是将/boot目录对应的分区格式的stage1.5文件复制到了0头0道3扇区开始向后的位置。。。stage1.5文件一般就10几k。。。够放了。。。 5、这样就可以顺利的识别文件系统然后转入stage2的运行了。。。stage2的入口在asm.S (我最早看grub的时候就是研究这个文件。。。实模式保护模式的转换。。。GDT初始化。。。C语言运行环境初始化。。。都是由这部分代码完成的。。。也就是说这部分代码完成了从汇编语言向C语言的进化。。。XD) 然后仔细看asm.s的代码会看到 [QUOTE]VARIABLE(config_file) #ifndef STAGE1_5 .string "/boot/grub/menu.lst" #else /* STAGE1_5 */ .long 0xffffffff .string "/boot/grub/stage2" #endif /* STAGE1_5 */[/QUOTE] 这下知道怎么找到menu.lst了吧。。。 6、asm.s将运行环境都初始化好了之后就进入c语言部分。。。这时转向stage2.c文件的cmain函数然后grub_open()函数(disk_io.c)去打开config_file。。。然后由print_entries等等函数吧菜单显示出来。。。不管是选了菜单选项还是输入grub命令。。。最后都交给comline.c文件里的find_command()函数去builtin.c文件里的struct builtin *builtin_table[]变量找指令。。。然后执行对应指令的xxx_func()函数(builtin.c)。。。 7、然后grub利用它自己在disk_io.c提供的一些函数去吧linux的内核加载进来。。。最后执行boot指令。。。移交控制权。。。然后拍拍屁股走人咯。。。剩下的是linuxkernel的事情了。。。 ——————————————俺是XE的分割线———————————— 上面说的是以grub0.97为例的grub1的启动流程和代码分析。。。 现在grub已经开始开发2了。。。最新版本是1.95 在grub2里引入了kernel。。。而且还有module。。。还真做成miniOS了。。。囧。。。 在grub2里就没有stage*了。。。 /boot/i386/pc/boot.S对应stage1.s完成stage1的功能。。。去读取0头0道2扇区的内容 而在0头0道2扇区开始存放的就是grub2里的kernel。。。编译之后的core.img文件才20几k对chs模式的0头0道64扇区(32k)来说都放的下。。。而这个20多k的小东西将完成stage1.5(10几k)+stage2(100多k)的功能 /kern/i386/pc/startup.s完成gurb1里asm.s的任务。。。然后转到c语言。。。 /kern/i386/pc/init.c完成kernel的初始化然后转交给/kern/main.c调用grub_load_modules()加载模块完成剩下的任务。。。 ——————————————LOLI飞过—————————————— 恩。。。就这么多吧。。。果然我还是晚上精神好。。。-ω- 我把grub0.97和grub1.95的源代码包都传上来。。。大家有兴趣就看看。。。 附件(949KB) grub-0.97.tar.gz 附件(507.1KB) grub-1.95.tar.gz 【 在 piaoice 的大作中提到: 】 : 给问住了:)有些地方去查下代码,也许能给出明确的答复。 : 阶段1,不论是启动linux还是win,都会经历这一步。关于BIOS的问题不能回答你。不过BIOS程序应该是放在只读存储器中。 : 阶段2,忘了以前在哪看的文档,BIOS应该会有跳转指令,将MBR中内容载入内存后,会去执行内存中相应的程序。 : ...................