嵌入式Linux内核启动首要分为这三个阶段
副问题[/!--empirenews.page--]
【资讯】嵌入式linux内核的启动全进程首要分为三个阶段。第一阶段为内核自解压进程,第二阶段首要事变是配置ARM处理赏罚器事变模式、使能MMU、配置一级页表等,而第三阶段则首要为C代码,包罗内核初始化的所有事变,下面是具体先容。 一、Linux内核自解压进程 在linux内核启动进程中一样平常能看到图1内核自解压界面,这里重点接头内核的自解压进程。 内核压缩息争压缩代码都在目次kernel/arch/arm/boot/compressed,编译完成后将发生head.o、misc.o、piggy.gzip.o、vmlinux、decompress.o这几个文件,head.o是内核的头部文件,认真初始配置;misc.o将首要认真内核的解压事变,它在head.o之后;piggy.gzip.o是一此中间文件,着实是一个压缩的内核(kernel/vmlinux),只不外没有和初始化文件及解压文件链接罢了;vmlinux是没有(zImage是压缩过的内核)压缩过的内核,就是由piggy.gzip.o、head.o、misc.o构成的,而decompress.o是为支持更多的压缩名目而新引入的。 图1 解压内核 在BootLoader完成体系的引导往后并将Linux内核调入内存之后,挪用do_bootm_linux(),这个函数将跳转到kernel的起始位置。假如kernel没有被压缩,就可以启动了。假如kernel被压缩过,则要举办解压,在压缩过的kernel头部有解压措施。压缩过的kernel进口第一个文件源码位置在arch/arm/boot/compressed/head.S。它将挪用函数decompress_kernel(),这个函数在文件arch/arm/boot/compressed/misc.c中,decompress_kernel()又挪用proc_decomp_setup(),arch_decomp_setup()举办配置,然后打印出信息“Uncompressing Linux...”后,挪用gunzip()将内核放于指定的位置。 下面简朴先容一下解压缩进程,也就是函数decompress_kernel实现的成果:解压缩代码位于kernel/lib/inflate.c,inflate.c是从gzip源措施中疏散出来的,包括了一些对全局数据的直接引用,在行使时必要直接嵌入到代码中。gzip压缩文件时老是在前32K字节的范畴内探求一再的字符串举办编码, 在解压时必要一个至少为32K字节的解压缓冲区,它界说为window[WSIZE]。inflate.c行使get_byte()读取输入文件,它被界说成宏来进步服从。输入缓冲区指针必需界说为inptr,inflate.c中对之有减量操纵。inflate.c挪用flush_window()来输出window缓冲区中的解压出的字节串,每次输出长度用outcnt变量暗示。在flush_window()中,还必需对输出字节串计较CRC而且革新crc变量。在挪用gunzip()开始解压之前,挪用makecrc()初始化CRC计较表。最后gunzip()返回0暗示解压乐成。我们在内核启动的开始城市看到这样的输出: UncompressingLinux...done, booting the kernel. 这也是由decompress_kernel函数输出的,执行完解压进程,再返回到head.S中的583行,启动内核 个中r4中已经在head.S的第180行处预置为内核镜像的地点,如下代码: 这样就进入Linux内核的第一阶段,我们也称之为stage1。 二、Linux内核启动第一阶段stage1 承接上文,这里以是说的第一阶段stage1就是内核解压完成并呈现Uncompressing Linux...done,booting the kernel.之后的阶段。 该部门代码实此刻arch/arm/kernel的 head.S中,该文件中的汇编代码通过查找处理赏罚器内核范例和呆板码范例挪用响应的初始化函数,再建 立页表,最后跳转到start_kernel()函数开始内核的初始化事变。检测处理赏罚器范例是在汇编子函数__lookup_processor_type中完成的,通过以下代码可实现对它的挪用:bl__lookup_processor_type(在文件head-commom.S实现)。__lookup_processor_type挪用竣事返回原措施时,会将返回功效生涯到寄存器中。个中r5寄存器返回一个用来描写处理赏罚器的布局体地点,并对r5举办判定,假如r5的值为0则声名不支持这种处理赏罚器,将进入__error_p。r8生涯了页表的符号位,r9 生涯了处理赏罚器的ID 号,r10生涯了与处理赏罚器相干的struct proc_info_list布局地点。Head.S焦点代码如下: 检测呆板码范例是在汇编子函数__lookup_machine_type (同样在文件head-common.S实现) 中完成的。与__lookup_processor_type相同,通过代码:“bl __lookup_machine_type”来实现对它的调 用。该函数返回时,会将返回布局生涯放在r5、r6 和r7三个寄存器中。个中r5寄存器返回一个用来描写呆板(也就是开拓板)的布局体地点,并对r5举办判定,假如r5的值为0则声名不支持这种呆板(开拓板),将进入__error_a,打印出内核不支持u-boot传入的呆板码的错误如图2。r6生涯了I/O基地点,r7 生涯了 I/O的页表偏移地点。 当检测处理赏罚器范例和呆板码范例竣事后,将挪用__create_page_tables子函数来成立页表,它所要做的事变就是将 RAM 基地点开始的1M 空间的物理地点映射到 0xC0000000开始的假造地点处。对本项目标开拓板DM3730而言,RAM挂接到物理地点0x80000000处,当挪用__create_page_tables 竣事后 0x80000000 ~ 0x80100000物理地点将映射到 0xC0000000~0xC0100000假造地点处。当全部的初始化竣事之后,行使如下代码来跳到C 措施的进口函数start_kernel()处,开始之后的内核初始化事变: bSYMBOL_NAME(start_kernel) 。 图2 呆板码不匹配错误 三、Linux内核启动第二阶段stage2 从start_kernel函数开始 (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |