




下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、X86 体系结构内核启动分析一、硬件检测当机器加电后它首先执行BIOS( 基本输入输出系统)中的代码, BIOS 首先执行加电自检程序 (POST) ,当自检通过程便完成了硬件的启动。当自检完成后BIOS 按照系统 COMS 中设置的启动顺序搜寻有效的启动驱动器(这里我们以硬盘为例),并读入系统引导扇区,并将系统控制权交给引导程序。二、加载和执行引导程序系统引导程序主要是把系统内核装载到内存,启动盘必须在第一个逻辑磁道上包含引导记录。这 512 个字节的扇区又被称作是引导扇区,在系统完成加电自检后,BIOS 从启动盘中将引导扇区读入到内存中。一旦引导记录加载完毕,BIOS 就交出系统的执行控制
2、权,跳转到引导程序的头部执行。有关 linux pc的引导程序 lilo 和 grub , lilo 和grub 可以引导多个系统,嵌入式系统上,最常见的 bootloader是UBOOT ,如果机器上要装多系统的话一般都会用到它们,这一引导程序也储存在引导扇区中或者存放在主引导记录中(MBR) , lilo 和grub 都许允用户自己配置,它们在系统安装时建立了关于系统内核占用磁盘数据块的位置对照表。比如, grub 程序就非常强大。Gurb 运行后,将初始化设置内核运行所需的环境。然后加载内核镜像。grub 磁盘引导全过程:stage1: grub读取磁盘第一个512 字节(硬盘的0 道
3、0 面 1 扇区,被称为MBR (主引导记录) ,也称为 bootsect)。 MBR 由一部分 bootloader的引导代码、分区表和魔数三部分组成。stage1_5:stage2:识别各种不同的文件系统格式。这使得加载系统引导菜单(/boot/grub/menu.lstgrub 识别到文件系统。或 grub.lst根据 grub版本不同文件位置会有所不同),加载内核vmlinuz和 RAM磁盘 initrd。有时候基本引导装载程序(stage1)不能识别stage2所在的文件系统分区,那么这时候就需要 stage 1.5 来连接stage1和 stage2了假设有如下grub配置代码ro
4、ot (hd0,0)/grub分区kernel /vmlinuz2.6.35.1074.fc14.i686 ro root=/dev/ram0/linux分区initrd /initramfs2.6.35.1074.fc14.i686.img要搞清楚上面两个root的关系,root (hd0,0)中的 root是 grub命令 ,它用来指定boot所在的分区作为grub的根目录.而 root=/dev/ram0是 kernel的参数,它告诉操作系统内核加载完毕之后,真实的文件系统所在的设备.要注意grub的根目录和文件系统的根目录的区别。kernel命令用来指定内核所在的位置,/代表 (hd0
5、,0),也就是 grub的根目录initrd命令用来指定初始化ram的 img文件所在位置。三、内核启动内核映像文件vmlinuz :包含有 linux 内核的静态链接的可执行文件,传统上,vmlinux被称为可引导的内核镜像。vmlinuz是 vmlinux的压缩文件。其构成如下:( 1)第一个512 字节(以前是在arch/i386/boot/bootsect.S) ?( 2)第二个,一段代码,若干个不多于512 字节的段(以前是在arch/i386/boot/setup.S) ?( 3)保护模式下的内核代码 (在 arch/x86/boot/main.c)。bzImage文件:使用mak
6、e bzImage命令编译内核源代码,可以得到采用zlib算法压缩的 zImage文件,即bigzImage文件。老的zImage解压缩内核到低端内存,bzImage则解压缩内核到高端内存(1M(0x100000)以上),在保护模式下执行。bzImage文件一般包含有vmlinuz、 bootsect.o、setup.o、解压缩程序misc.o、以及其他一些相关文件(如 piggy.o)。注意,在Linux 2.6内核中,bootsect.S和setup.S被整合为header.S。initramfs(或 initrd)文件:initrd是 initialized ram disk的意思。主要
7、用于加载硬件驱动模块,辅助内核的启动,挂载真正的根文件系统。装载 Linux内核的第一步应该是加载实模式代码(boot sector和 setup代码),grub就会把实模式代码setup加载到0x07C00之上的某个地址上,其中setup的前 512 个字节是bootsector (引导扇区),现在这个引导扇区的作用并不是用来引导系统,而是为了兼容及传递一些参数。之后grub跳转到setup的入口点,入口点为_start例程 (根据arch/x86/boot/setup.ld可知 )。然后 setup最后跳到arch/x86/boot/main.c再经过一系列的跳转,跳到start_kern
8、el()函数,这是Linux内核的启动函数。main.c文件是整个Linux内核的中央联结点。每种体系结构都会执行一些底层设置函数,然后执行名为start_kernel的函数(在init/main.c中可以找到这个函数)。可以认为main.c是内核的 “粘合剂(glue) ”,之前执行的代码都是各种体系结构相关的代码,一旦到达start_kernel(),就与体系结构无关了。start_kernel()会调用一系列初始化函数来设置中断,执行进一步的内存配置,解析内核命令行参数。然后调用fs/dcache.c:vfs_caches_init()-fs/namespace.c:mnt_init()
9、创建基于内存的rootfs文件系统(是一个虚拟的内存文件系统,称为VFS),这是系统初始化时的根结点,即/结点,后面VFS会指向真实的文件系统。 fs/namespace.c:mnt_init()会调用 fs/ramfs/inode.c:init_rootfs()会调用fs/filesystems.c:register_filesystem()注册 rootfs。然后fs/namespace.c:init_mount_tree()调用 fs/super.c:do_kern_mount()在内核中挂载rootfs,调用fs/fs_struct.c:set_fs_root()将当前的rootfs文
10、件系统配置为根文件系统。此时rootfs里只有根目录。为什么不直接把真实的文件系统配置为根文件系统?答案很简单,内核中没有真实根文件系统设备(如硬盘,USB )的驱动,而且即便你将根文件系统的设备驱动编译到内核中,此时它们还尚未加载,实际上所有内核中的驱动是由后面的kernel_init线程进行加载。另外,我们的root 设备都是以设备文件的方式指定的,如果没有根文件系统,设备文件怎么可能存在呢?start_kernel()在最后会调用 rest_init(),这个函数会启动一个内核线程来运行kernel_init(),自己则调用cpu_idle() 进入空闲循环,让调度器接管控制权。抢占式的
11、调度器就可以周期性地接管控制权,从而提供多任务处理能力。kernel_init()用于完成初始化rootfs 、加载内核模块、挂载真正的根文件系统。(因为已经初始化了 rootfs ,而且还加载了内核模块,所以可以找到设备如硬盘、内存,然后就可以把分区设置为根设备,并在根设备上挂载文件系统)挂载完真正的根文件系统后,goto到out,将挂载点从当前目录移到/,并把/作为系统的根目录,至此虚拟文件系统切换到了实际的根文件系统。目前 2.6 的 kernel支持三方式来挂载最终的根文件系统:( 1)所有需要的设备和文件系统驱动被编译进内核,没有initrd 。通过 “root=参数指定的根设备,
12、init/main.c:kernel_init()将调用 prepare_namespace()直接在指定的根设备上挂载最终的根文件系统。通过可选的init= 选项,还可以运行用户指定的init 程序。( 2)一些设备和文件驱动作为模块来构建并存放的initrd 中。 initrd 被称为 ramdisk ,是一个独立的小型文件系统。它需要包含/linuxrc 程序(或脚本),用于加载这些驱动模块,并挂载最终的根文件系统(这个根文件系统在pc平台存放在硬盘上,结合使用 pivot_root 系统调用),然后initrd 被卸载。 initrd 由 prepare_namespace()挂载和运
13、行。内核必须要使用CONFIG_BLK_DEV_RAM(支持 ramdisk )和 CONFIG_BLK_DEV_INITRD(支持 initrd )选项进行编译才能支持initrd 。(方法 1只挂载了一次文件系统,而这个方法挂载了两次)initrd 文件通过在 grub 引导时用 initrd 命令指定。它有两种格式,一种是类似于linux2.4内核使用的传统格式的文件系统镜像,称之为imageinitrd ,它的制作方法同Linux2.4 内核的initrd 一样,其核心文件就是/linuxrc 。另外一种格式的initrd 是 cpio 格式的,这种格式的initrd 从 linux
14、2.5 起开始引入,使用cpio 工具生成,其核心文件不再是/linuxrc ,而是 /init ,这种initrd 称为 cpioinitrd 。为了向后兼容,linux2.6 内核对 cpioinitrd和imageinitrd 这两种格式的initrd处理与 initramfs 类似,会直接跳过均支持,但对其处理流程有着显著的区别。cpioinitrd的prepare_namespace(),imageinitrd的处理则由prepare_namespace()进行。( 3)使用 initramfs 。 prepare_namespace() 调用会被跳过。这意味着必须有一个程序来完成这
15、些工作。这个程序是通过修改usr/gen_init_cpio.c的方式,或通过新的initrd 格式(一个 cpio 归档文件)存放在initramfs 中的,它必须是/init 。这个程序负责prepare_namespace()所做的所有工作。为了保持向后兼容,在现在的内核中,/init 程序只有是来自 cpio 归档的情况才会被运行。如果不是来自cpio 归档, init/main.c:kernel_init()将运行 prepare_namespace()来挂载最终的根文件系统,并运行一个预先定义的init 程序(或者是用户通过 init= 指定的,或者是/sbin/init , /e
16、tc/init , /bin/init )。 initramfs 是从 2.5 kernel开始引入的一种新的实现机制。顾名思义,initramfs 只是一种 RAM filesystem 而不是 disk 。initramfs 实际是一个包含在内核映像内部的cpio 归档,启动所需的用户程序和驱动模块被归档成一个文件。因此,不需要cache ,也不需要文件系统。编译 2.6 版本的 linux 内核时,编译系统总会创建 initramfs ,然后通过连接脚本 archx86kernelvmlinux.lds.S把它与编译好的内核连接成一个文件,它被链接到地址_initramfs_start_
17、initramfs_end处。内核源代码树中的 usr 目录就是专门用于构建内核中的initramfs 的。缺省情况下, initramfs 是空的, X86 架构下的文件大小是134 个字节。实际上它的含义就是:在内核镜像中附加一个cpio 包,这个 cpio 包中包含了一个小型的文件系统,当内核启动时,内核将这个cpio 包解开,并且将其中包含的文件系统释放到rootfs 中,内核中的一部分初始化代码会放到这个文件系统中,作为用户层进程来执行。这样带来的明显的好处是精简了内核的初始化代码,而且使得内核的初始化过程更容易定制。注意initramfs 和 initrd 都可以是 cpio 包,
18、可以压缩也可以不压缩。但 initramfs 是包含在内核映像中的,作为内核的一部分存在,因此它不会由bootloader (如 grub )单独地加载,而initrd 是另外单独编译生成的,是一个独立的文件,会由 bootloader 单独加载到 RAM 中内核空间以外的地址处。目前initramfs 只支持 cpio 包格式,它会被populate_rootfsunpack_to_rootfs(&_initramfs_start, &_initramfs_end&_initramfs_start, 0) 函数解压、解析并拷贝到根目录。initramfs被解析处理后原始的cpio包( 压缩或
19、非压缩 )所占的空间 (&_initramfs_start &_initramfs_end)是作为系统的一部分直接保留在系统中,不会被释放掉。而对于initrd 镜像文件,如果没有在命令行中设置keepinitd命令,那么 initrd 镜像文件被处理后其原始文件所占的空间(initrd_endinitrd_start)将被释放掉。四、启动应用程序prepare_namspace执行完后,真正的文件系统就挂载成功。转入init_post(),它用来运行用户空间的第一个进程,即众所周知的init进程,在我的ubuntu下, init先读/etc/init/下的配置文件,配置文件描述了运行级别、等
20、,并通过从/etc/rcX.d目录到/etc/init.d目录的初始化脚本的链接来启动与终止系统服务。执行相关脚本,以完成系统初始化,如设置键盘、字体,装载模块,设置网络等,最后运行登录程序,出现登录界面。运行用户空间中的init 进程可能是以下几种情况:( 1) noinitrd方式,则直接运行用户空间中的/sbin/init(或 /etc/init,/bin/init),作为第一个用户进程。( 2)传统的 imageinitrd 方式。运行的第一个程序是 /linuxrc 脚本,由它来启动用户空间中的 init 进程。( 3) cpioinitrd和 initramfs方式。运行的第一个程序是/init 脚本,由它来启动用户空间中的 init 进程。总的来说, x86 架构的 Linux 内核启动过程分为6大步,分别为:( 1)实模式的入口函数_start():在 header.S中,这里会进入众所周知的main 函数,它拷贝bootloader的各个参数,执行基本硬件设置,解
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2019年党建知识竞赛简答题题库及答案
- 2025年国内贸易买卖合同范本下载
- 2025合伙权益解决方案合同协议书
- 2025中国建设银行贷款合同范本
- 2025合法的服装分销合同协议
- 2025年农村果园承包合同范本
- 2025云端存储合同范本
- 企业安全培训巡查课件
- 2022年五险一金培训
- 超声监测眼晶状体变化-洞察及研究
- 桥梁检测评定与加固技术(第2版) 课件 第6章 桥梁检查与评定
- 兼职健身教练合作协议3篇
- 粮食安全政策
- UL2034标准中文版-2017一氧化碳报警器UL中文版标准
- 【MOOC】认识飞行-上海工程技术大学 中国大学慕课MOOC答案
- 国际商务谈判 习题答案、练习题及答案(白远)
- 关节活动维持与改善技术
- 幼儿园饮用水突发污染事故应急处理预案
- 政治-中国特色社会主义教材探究与分享参考答案高中政治统编版必修一
- 湖南省长沙市师大附中博才实验中学2024-2025学年九年级上学期开学考试语文试题
- 《赏书法之韵》教学课件1
评论
0/150
提交评论