首页 linux内核启动流程总结

linux内核启动流程总结

举报
开通vip

linux内核启动流程总结X86体系结构内核启动分析—、硬件检测当机器加电后它首先执行BIOS(基本输入输出系统)中的代码,BIOS首先执行加电自检程序(POST),当自检通过程便完成了硬件的启动。当自检完成后BIOS按照系统COMS中设置的启动顺序搜寻有效的启动驱动器(这里我们以硬盘为例),并读入系统引导扇区,并才各系统控制权交给引导程序。二、加载和执行引导程序系统引导程序主要是把系统内核装载到内存,启动盘必须在第一个逻辑磁道上包含引导记录。这512个字节的扇区又被称作是引导扇区,在系统完成加电自检后,BIOS从启动盘中将引导扇区读入到内...

linux内核启动流程总结
X86体系结构内核启动分析—、硬件检测当机器加电后它首先执行BIOS(基本输入输出系统)中的代码,BIOS首先执行加电自检程序(POST),当自检通过程便完成了硬件的启动。当自检完成后BIOS按照系统COMS中设置的启动顺序搜寻有效的启动驱动器(这里我们以硬盘为例),并读入系统引导扇区,并才各系统控制权交给引导程序。二、加载和执行引导程序系统引导程序主要是把系统内核装载到内存,启动盘必须在第一个逻辑磁道上包含引导记录。这512个字节的扇区又被称作是引导扇区,在系统完成加电自检后,BIOS从启动盘中将引导扇区读入到内存中。一旦引导记录加载完毕,BIOS就交出系统的执行控制权,M備到引导程序的头部执行。有关linuxpc的引导程序lilo和grub,liIo和grub可以引导多个系统,嵌入式系统上,最常见的bootloader是UBOOT,如果机器上要装多系统的话一般都会用到它们,这一引导程序也储存在引导扇区中或者存放在主引导记录中(MBR),lilo和grub都许允用户自己配置,它们在系统安装时建立了关于系统内核占用磁盘娄块的位置对照表。比如,grub程序就^常强大。Gurb运行后,耕刀始化设置内核运行所需的环境。然后加载内核璜像。grub磁盘引导全过程:stagel:grub读取磁盘第一个512字节(硬盎的0道0面1扇区,被称为MBR(主引导记录),也称为bootsect)。MBR由冷分bootloader的引导代码、分区表和魔数三部分纟鹹stagel_5:识别各种不同的文件系统 格式 pdf格式笔记格式下载页码格式下载公文格式下载简报格式下载 。这使得grub识别到文件系统。stage2:加载系统引导菜单(/boot/grub/menu.lst或grub.lst根据grub版本不同文件位置会有所不同),加载内核vmlinuz和RAM磁盘initrd。有时候基本引导装载程序(stagel)不能识别stage2所在的文件系统分区,那么这时候就需要stagel.5来连接stagel和stage2了假设有如下grub配置代码root(hd0,0)//grub分区kernel/vmlinuz-2.6.35.10-74.fcl4.i686roroot=/dev/ramO//linux分区initrd/initramfs-2.6.35.10-74.fcl4.i686.img要搞清楚上面两个root的关系,root(hd0,0)中的root是grub命令它用来指走boot所在的分区作为grub的根目录.r?oroot=/dev/ram0是kernel的参数它告诉操作系统内核加载完毕之后,真实的文件系统所在的设备•要注意grub的根目录和文件系统的根目录的区别。kernel命令用来指走内核所在的位置,7"代表(hd0,0),也就是grub的根目录initrd命令用来指走初始化ram的img文件所在位置。三、内核启动内核映像文件vmlinuz:包含有linux内核的静态链接的可执行文件,传统上,vmlinux被称为可引导的内核谯像。vmlinuz是vmlinux的压缩文件。其构成如下:第一个512字节(以前是在arch/i386/boot/bootsect.S);(2)第二个,一段代码,若干个不多于512字节的段(以前是在arch/i386/boot/setup.S);(3)保护模式下的内核代码(在arch/x86/boot/main.c)。bzlmage文件:使用makebzlmage命令编译内核源代码,可以得到采用zlib算法压缩的zlmage文件,即bigzlmage文件。老的zlmage解压缩内核到低端内存,bzlmage则解压缩内核到高端内存((0x100000)以上),在保护模式下执行。bzlmage文件一般包含有vmlinuz、bootsect.o,setup.。、解压缩程序misc.o、以及其他一些相关文件(如piggy.o)。注意,在Linux2.6内核中,bootsect.S和setup.S被整合为header.Soinitramfs(或initrd)文件:initrd是initializedramdisk的意思。主要用于加载硬件驱动模块,辅助内核的启动,挂载真正的根文件系统。装载Linux内核的第書应该是加载实模式代码(bootsector和setup]弋码),grub就会把实模式代码$。山卩加载^(^07(200之上的某个地址上,其中setup的前512个字节是bootsector(引导扇区),现在这个引导扇区的作用并不是用来弓I导系统,而是为了蒸容及传递一些参数。之后grub财儼到setup的入口点,入口点为一start例程(根据arch/x86/boot/setup.ld可知)。然后setup最后®^ijarch/x86/boot/main.c再经过一系列的跳转,協倒start_kernel()函数,这是Linux内核的启动函数。main.c文件是整个Linux内核的中央联结点。每种体系结构都会执行一些底层设置函数,然后执行名为start_kernel0<)函数(在init/main.c中可以找到这个函数)。可以认为main.c是内核的"粘合齐U(glue)",之前执行的代码都是各种体系结构相关的代码,—旦到达start_kernel(),就与体系结构无关了。start_kernel()会调用一系列初始化函数来设置中断,执行逬一步的内存配置,解析内核命令行参数。然后调用fs/dcache.c:vfs_caches_initO…->fs/namespace.c:mnt_initO创建基于内存的rootfs文件系统(是一个虚拟的内存文件系统,称为VFS),这是系统初始化时的根结点,即7"结点,后面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文件系统酉£置为根文件系统。此时rootfs里只有根目录。为什么不直接把真实的文件系统配置为根文件系统?答案很简单,内核中没有真实根文件系统设备(如硬盘,USB)的驱动,而且即便你将根文件系统的设备驱动编译到内核中,此时它们还尚未加载,实际上所有内核中的驱动是由后面的kemel」nit线程进行加载。另外,我们的root设备都是以设备文件的方式指定的,如果没有根文件系统,设备文件怎么可能存在呢?start_kernel()在最后会调用rest」nit(),这个函数会启动一个内核线程来运行kernel_init(),自己则调用cpu_idle()进入空闲循环,让调度器接管控制权。抢占式的调度器就可以周期性地接管控制权,从而提供多任务处理能力。kerneIJnitO用于完成初始化rootfs.加载内核模块、挂载真正的根文件系统。(因为已经初始化了rootfs,而且还加载了内核模块,所以可以找至iJ设备如硬盘、内存,然后就可以把分区设置为根设备,并在根设备上挂载文件系统)挂载完真正的根文件系统后,goto到out,将挂载点从当前目录移到"/",并把"/"作为系统的根目录,至此虚拟文件系统切换到了实际的根文件系统。目前2.6的kernel支持三方式来挂载最终的根文件系统:所有需要的设备和文件系统驱动被编译进内核,没有initrd.通过"root二"参数指定的根设init/main.c:kemel_init()将调用prepare_namespace()直接在指定的根设备上挂载最终的根文件系统。通过可选的”init=”选项,还可以运行用户指立的init程序。一些设备和文件驱动作为模块来构建并存放的initrd中。initrd被称为ramdisk,是一个独立的小型文件系统。它需要包含/linuxrc程序(或脚本),用于加载这些驱动模块,并挂载最终的根文件系统(这个根文件系统在pc平台存放在硬盘上,结合使用pivot_root系统调用),然后initrd被卸载。initrd由prepare_namespace()挂载和运行。内核必须要使用CONFIG_BLK_DEV_RAM(支持ramdisk)和CONFIG_BLK_DEV」NITRD(支持initrd)选项进行编译才能支持initrd.(方法1只挂载了一次文件系统,而这个方法挂载了两次)initrd文件通过在grub引导时用initrd命令指左。它有两种格式,一种是类似于Iinux2.4内核使用的传统格式的文件系统镜像,称之为imageinitrd,它的制作方法同Linux2.4内核的initrd—样,其核心文件就是/linuxrc。另外一种格式的initrd是cpio格式的,这种格式的initrd从linux2.5起开始引入,使用cpio工具生成,其核心文件不再是/linuxrc,而是/init,这种initrd称为cpioinitrd。为了向后兼容,Iinux2.6内核对cpioinitrd和imageinitrd这两种格式的initrd均支持,但对其处理 流程 快递问题件怎么处理流程河南自建厂房流程下载关于规范招聘需求审批流程制作流程表下载邮件下载流程设计 有着显著的区别。cpioinitrd的处理与initramfs类似,会直接跳过prepare_namespace(),imageinitrd的处理贝ij由prepare_namespace()进行。使用initramfsoprepare_namespace()调用会被跳过。这意味着必须有一个程序来完成这些工作。这个程序是通过修改usr/gen_init_cpio.c的方式,或通过新的initrd格式(一个cpio归档文件)存放在initramfs中的,它必须是7init\这个程序负责prepare_namespace()所做的所有工作。为了保持向后兼容,在现在的内核中,/init程序只有是来自cpio归档的情况才会被运行。如果不是来自cpio归档,init/main.c:kemel_init()将运行prepare_namespace()来挂载最终的根文件系统,并运行一个预先立义的init程序(或者是用户通过泊让=指定的,或者是/sbin/init,/etc/init,/bin/init)。initramfs是从2.5kernel开始引入的一种新的实现机制。顾名思义‘initramfs只是一种RAMfilesystem而不是disk,initramfs实际是一个包含任内核映像内部的cpio归档,启动所需的用户程序和驱动模块被归档成一个文件。因此不需要cache,也不需要文件系统。编译2.6版本的linux内核时,编译系统总会创建initramfs,然后通过连接脚本arch\x86\kernel\vmlinux.lds.S把它与编译好的内核连接成一个文件,它被链接到地址—initramfs_start~_initramfs_end处。内核源代码树中的usr目录就是专门用于构建内核中的initramfs的。缺省情况下,initramfs是空的,X86架构下的文件大小是134个字节。实际上它的含义就是:在内核镜像中附加一个cpio包,这个cpio包中包含了一个小型的文件系统,当内核启动时,内核将这个cpio包解开,并且将其中包含的文件系统释放到rootfs中,内核中的一部分初始化代码会放到这个文件系统中,作为用户层进程来执行。这样带来的明显的好处是精简了内核的初始化代码,而且使得内核的初始化过程更容易左制。注意initramfs和initrd都可以是cpio包,可以压缩也可以不压缩。但initramfs是包含在内核映像中的,作为内核的一部分存在,因此它不会由bootloader(如grub)单独地加载,而initrd是另外单独编译生成的,是一个独立的文件,会由bootloader单独加载到RAM中内核空间以外的地址处。目前initramfs只支持cpio包格式,它会被populate_rootfs>unpack_to_rootfs(&_initramfs_start,&_initramfs_end&_initramfs_start,0)函数解压、解析并拷贝到根目录°initramfs被解析处理后原始的cpio包(压缩或非压缩)所占的空间(&__initramfs_start&_initramfs_end)是作为系统的一部分直接保留在系统中,不会被释放掉。而对于initrd镜像文件,如果没有在命令行中设宜"keepinitd"命令,那么initrd镜像文件被处理后其原始文件所占的空间(initrd_endinitrd_start)W被释放掉。四、启动应用程序prepare_namspace执行完后,真正的文件系统就挂载成功。转入init_post(),它用来运行用户空间的第一个逬程,即众所周知的init进程,在我的ubuntu下,init先读/etc/init/T的酉櫃文件,配置文俐苗述了运行级别、等,并通过从/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大步,分別为:实模式的入口函数_start():在header.S中,这里会进入众所周知的main函数,它拷贝bootloader的各个参数,执行基本硬件设宜,解析命令行参数。保护模式的入口函数startup_32():在compressed/header_32.S中,这里会解压bzlmage内核映像,加载vmlinux内核文件。内核入口函数startup_32():在kernel/header_32.S中,这就是所谓的进程0,它会进入体系结构无关的start_kernel()函数,即众所周知的Linux内核启动函数。start_kernel()会做大量的内核初始化操作,解析内核启动的命令行参数,并启动一个内核线程来完成内核模块初始化的过程,然后进入空闲循环。内核模块初始化的入口函数kernel_init():在init/main.c中,这里会启动内核模块、创建基于内存的rootfs、加载initramfs文件或cpioinitrd,并启动一个内核线程来运行其中的/init脚本,完成真正根文件系统的挂载。根文件系统挂载脚本/init:这里会挂载根文件系统、运行/sbin/init,从而启动众所周知的进程1。init进程的系统初始化过程:执行相关脚本,以完成系统初始化,如设置键盘、字体,装载模块,设置网络等,最后运行登录程序,出现登录界而。如果从体系结构无关的视角来看,start_kemel()nj以看作时体系结构无关的Linuxmain函数,它是体系结构无关的代码的统一入口函数,这也是为什么文件会命名为init/main.c的原因。这个main.c粘合剂把各种体系结构的代码"粘合倒一个统一的入口处。
本文档为【linux内核启动流程总结】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_179289
暂无简介~
格式:doc
大小:102KB
软件:Word
页数:6
分类:
上传时间:2018-05-18
浏览量:0