LINUX内核引导启动程序_第1页
LINUX内核引导启动程序_第2页
LINUX内核引导启动程序_第3页
LINUX内核引导启动程序_第4页
LINUX内核引导启动程序_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

LINUX内核引导程序武汉大学计算机学院郑鹏Email:pzheng51@163.comLINUX系统初始化11.当PC启动时,Intel系列的CPU首先进入的是实模式,并开始执行位于地址0xFFFF0处的代码(只用于实模式高地址位忽略),也就是ROM-BIOS起始位置的代码。BIOS先进行一系列的系统自检,然后初始化位于地址0的中断向量表。最后BIOS将启动盘的第一个扇区,也就是bootsect.S,装入到0x7C00(31K)处,并开始执行此处的代码。LINUX系统初始化22.当bootsect.S开始运行时,将自己装入到绝对地址0x90000(576K)处,再将其后的2k字节代码(boot/setup.s)装入到地址0x90200处,最后将核心的其余部分(system模块)装入到0x10000。当系统装入时,会显示Loading...信息。装入完成后,控制转向另一个实模式下的汇编语言代码boot/setup.S。因为当时system模块的长度不会超过0x80000字节大小(即512KB),所以它不会覆盖在0x90000处开始的bootsect和setup模块。随后将system模块移动到内存起始处,这样system模块中代码的地址也即等于实际的物理地址。便于对内核代码和数据的操作。LINUX系统初始化33.Setup部分首先设置一些系统的硬件设备,然后将核心从0x10000处移至0x1000处。这时系统转入保护模式,开始执行位于0x1000处的代码。LINUX系统初始化44.接下来是内核的解压缩。0x1000处的代码来自于文件zBoot/head.S,它用来初始化寄存器和调用decompress_kernel()程序。decompress_kernel()程序由zBoot/inflate.c,zBoot/unzip.c和zBoot/misc.c组成。解压缩后的数据被装入到了0x100000处,这也是Linux不能在内存小于2M的环境下运行的主要原因。5.解压后的代码在0x1010000处开始执行,紧接着所有的32位的设置都将完成:IDT、GDT和LDT将被装入,处理器初始化完毕,设置好内存页面,最终调用start_kernel过程。这大概是整个内核中最为复杂的部分。LINUX系统初始化56.start_kernel()程序用于初始化系统内核的各个部分,包括:设置内存边界,调用paging_init()初始化内存页面。初始化陷阱,中断通道和调度。对命令行进行语法分析。初始化设备驱动程序和磁盘缓冲区。校对延迟循环。7.最后,系统核心转向move_to_user_mode(),以便创建初始化进程(init)。此后,进程0开始进入无限循环。LINUX系统初始化6启动引导时内核在内存中的位置和移动后的位置情况bootsect.s程序功能描述bootsect.s代码是磁盘引导块程序,驻留在磁盘的第一个扇区中(引导扇区,0磁道(柱面),0磁头,第1个扇区)。在PC机加电ROMBIOS自检后,引导扇区由BIOS加载到内存0x7C00处,然后将自己移动到内存0x90000处。该程序的主要作用是首先将setup模块(由setup.s编译成)从磁盘加载到内存,紧接着bootsect的后面位置(0x90200),然后利用BIOS中断0x13取磁盘参数表中当前启动引导盘的参数,接着在屏幕上显示“Loadingsystem...”字符串。再者将system模块从磁盘上加载到内存0x10000开始的地方。随后确定根文件系统的设备号,若没有指定,则根据所保存的引导盘的每磁道扇区数判别出盘的类型和种类(是1.44MA盘?)并保存其设备号于root_dev(引导块的0x508地址处),最后长跳转到setup程序的开始处(0x90200)执行setup程序。setup.s程序功能描述setup程序的作用主要是利用ROMBIOS中断读取机器系统数据,并将这些数据保存到0x90000开始的位置(覆盖掉了bootsect程序所在的地方)。内核相关程序使用这些参数将。然后setup程序将system模块从0x10000-0x8ffff(当时认为内核系统模块system的长度不会超过此值:512KB)整块向下移动到内存绝对地址0x00000处。接下来加载中断描述符表寄存器(idtr)和全局描述符表寄存器(gdtr),开启A20地址线,重新设置两个中断控制芯片8259A,将硬件中断号重新设置为0x20-0x2f。最后设置CPU的控制寄存器CR0(也称机器状态字),从而进入32位保护模式运行,并跳转到位于system模块最前面部分的head.s程序继续运行。为了能让head.s在32位保护模式下运行,在本程序中临时设置了中断描述符表(idt)和全局描述符表(gdt),并在gdt中设置了当前内核代码段的描述符和数据段的描述符。在下面的head.s程序中会根据内核的需要重新设置这些描述符表。setup.s程序在setup.s程序执行结束后,系统模块system被移动到物理地址0x0000开始处,而从0x90000处则存放了内核将会使用的一些系统基本参数。此时临时全局表中有三个描述符,第一个是(NULL)不用,另外两个分别是代码段描述符和数据段描述符。它们都指向系统模块的起始处,也即物理地址0x0000处。这样当setup.s中执行最后一条指令'jmp0,8'(第193行)时,就会跳到head.s程序开始处继续执行下去。这条指令中的'8'是段选择符,用来指定所需使用的描述符项,此处是指gdt中的代码段描述符。'0'是描述符项指定的代码段中的偏移值。setup.s程序setup.s程序结束后内存中程序示意图head.s程序head.s程序在被编译后,会被连接成system模块的最前面开始部分,这也就是为什么称其为头部(head)程序的原因。从这里开始,内核完全都是在保护模式下运行了。head.s汇编程序与前面的语法格式不同,它采用的是AT&T的汇编语言格式,并且需要使用GNU的gas和gld2进行编译连接。因此请注意代码中赋值的方向是从左到右。head.s程序这段程序实际上处于内存绝对地址0处开始的地方。首先是加载各个数据段寄存器,重新设置中断描述符表idt,共256项,并使各个表项均指向一个只报错误的哑中断程序。然后重新设置全局描述符表gdt。接着使用物理地址0与1M开始处的内容相比较的方法,检测A20地址线是否已真的开启(如果没有开启,则在访问高于1Mb物理内存地址时CPU实际只会访问(IPMOD1Mb)地址处的内容),如果检测下来发现没有开启,则进入死循环。然后程序测试PC机是否含有数学协处理器芯片(80287、80387或其兼容芯片),并在控制寄存器CR0中设置相应的标志位。接着设置管理内存的分页处理机制,将页目录表放在绝对物理地址0开始处(也是本程序所处的物理内存位置,因此这段程序将被覆盖掉),紧随后面放置共可寻址16MB内存的4个页表,并分别设置它们的表项。最后利用返回指令将预先放置在堆栈中的/init/main.c程序的入口地址弹出,去运行main()程序。head.s程序head.s程序执行结束后,已经正式完成了内存页目录和页表的设置,并重新设置了内核实际使用的中断描述符表idt和全局描述符表gdt。另外还为软盘驱动程序开辟了1KB字节的缓冲区。head.s程序system模块在内存中的映像示意图Intel32位保护运行机制CPU在实模式运行方式时,段寄存器用来放置一个内存段地址(比如0x9000),而此时在该段内可以寻址64KB的内存。但当进入保护模式运行方式时,此时段寄存器中放置的并不是内存中的某个地址值,而是指定描述符表中某个描述符项相对于该描述符表基址的一个偏移量。在这个8字节的描述符中含有该段线性地址的‘段’基址和段的长度,以及其它一些描述该段特征的比特位。因此此时所寻址的内存位置是这个段基址加上当前执行代码指针eip的值。而当前描述符表的基地址则保存在描述符表寄存器中,如全局描述符表寄存器gdtr、中断门描述符表寄存器idtr,加载这些表寄存器须使用专用指令lgdt或lidt。当然,此时所寻址的实际物理内存地址,还需要经过内存页面处理管理机制进行变换后才能得到。简而言之,32位保护模式下的内存寻址需要经过描述符表中的描述符和内存页管理来确定。Intel32位保护运行机制针对不同的使用方面,描述符表分为三种:全局描述符表(GDT)中断描述符表(IDT)局部描述符表(LDT)当CPU运行在保护模式下,某一时刻GDT和IDT分别只能有一个,分别由寄存器GDTR和IDTR指定它们的表基址。局部表可以有0-8191个,其基址由当前LDTR寄存器的内容指定,是使用GDT中某个描述符来加载的,也即LDT也是由GDT中的描述符来指定。但是在某一时刻同样也只有其中的一个被认为是活动的。一般对于每个任务(进程)使用一个LDT。在运行时,程序可以使用GDT中的描述符以及当前任务的LDT中的描述符。Intel32位保护运行机制中断描述符表IDT的结构与GDT类似,在Linux内核中它正好位于GDT表的后面。共含有256项8字节的描述符。但每个描述符项的格式与GDT的不同,其中存放着相应中断过程的偏移值(0-1,6-7字节)、所处段的选择符值(2-3字节)和一些标志(4-5字节)。Intel32位保护运行机制Linux内核中所使用的描述符表在内存中的示意图系统运行初始化进程开始执行/etc/init、/bin/init或/sbin/init中的一个之后,系统内核就不再对程序进行直接控制了。之后系统内核的作用主要是给进程提供系统调用,以及提供异步中断事件的处理。多任务机制已经建立起来,并开始处理多个用户的登录和fork()创建的进程。内核提供的各种系统调用进程的基本概念和系统的基本数据结构从系统内核的角度看来,一个进程仅仅是进程控制表(processtable)中的一项。进程控制表中的每一项都是一个task_struct结构,而task_struct结构本身是在include/linux/sched.h中定义的。在task_struct结构中存储各种低级和高级的信息,包括从一些硬件设备的寄存器拷贝到进程的工作目录的链接点。进程控制表既是一个数组,又是一个双向链表,同时又是一个树。其物理实现是一个包括多个指针的静态数组。此数组的长度保存在include/linux/tasks.h定义的常量NR_TASKS中,其缺省值为128,数组中的结构则保存在系统预留的内存页中。链表是由next_task和prev_task两个指针实现的,而树的实现则比较复杂。内核提供的各种系统调用进程的基本概念和系统的基本数据结构系统启动后,内核通常作为某一个进程的代表。一个指向task_struct的全局指针变量current用来记录正在运行的进程。变量current只能由kernel/sched.c中的进程调度改变。当系统需要查看所有的进程时,则调用for_each_task,这将比系统搜索数组的速度要快得多。某一个进程只能运行在用户方式(usermode)或内核方式(kernelmode)下。用户程序运行在用户方式下,而系统调用运行在内核方式下。在这两种方式下所用的堆栈不一样:用户方式下用的是一般的堆栈,而内核方式下用的是固定大小的堆栈(一般为一个内存页的大小)。内核提供的各种系统调用创建进程Linux系统使用系统调用fork()来创建一个进程,使用exit()来结束进程。fork()和exit()的源程序保存在kernel/fork.candkernel/exit.c中。fork()的主要任务是初始化要创建进程的数据结构,其主要的步骤有:1)申请一个空闲的页面来保存task_struct。2)查找一个空的进程槽(find_empty_process())。3)为kernel_stack_page申请另一个空闲的内存页作为堆栈。4)将父进程的LDT表拷贝给子进程。5)复制父进程的内存映射信息。6)管理文件描述符和链接点。内核提供的各种系统调用撤消进程撤消一个进程可能稍微复杂些,因为撤消子进程必须通知父进程。另外,使用kill()也可以结束一个进程。sys_kill()、sys_wait()和sys_exit()都保存在文件exit.c中。内核提供的各种系统调用执行程序使用fork()创建一个进程后,程序的两个拷贝都在运行。通常一个拷贝使用exec()调用另一个拷贝。系统调用exec()负责定位可执行文件的二进制代码,并负责装入和运行。Linux系统中的exec()通过使用linux_binfmt结构支持多种二进制格式。每种二进制格式都代表可执行代码和链接库。linux_binfmt结构种包含两个指针,一个指向装入可执行代码的函数,另一个指向装入链接库的函数。Unix系统提供给程序员6种调用exec()的方法。其中的5种是作为库函数实现,而sys_execve()是由系统内核实现的。它执行一个十分简单的任务:装入可执行文件的文件头,并试图执行它。如果文件的头两个字节是#!,那么它就调用在文件第一行中所指定的解释器,否则,它将逐个尝试注册的二进制格式。存取文件系统文件系统是Unix系统最基本的资源。最初的Unix系统一般都只支持一种单一类型的文件系统,在这种情况下,文件系统的结构深入到整个系统内核中。而现在的系统大多都在系统内核和文件系统之间提供一个标准的接口,这样不同文件结构之间的数据可以十分方便地交

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论