ImageVerifierCode 换一换
格式:DOCX , 页数:12 ,大小:133.66KB ,
资源ID:14353694      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bingdoc.com/d-14353694.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Linux的启动过程分析资料.docx)为本站会员(b****1)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

Linux的启动过程分析资料.docx

1、Linux的启动过程分析资料 嵌入式系统期中大作业 题目:Linux的启动过程分析 学 院:信息工程 专 业:网络工程 姓 名:梁法成 学 号:201324070128 2016.4.15 目 录1.从开机加电到执行main函数之前的过程 1.1启动BIOS,准备实模式下的中断向量表和中断服务程序 1.1.1BIOS的启动原理 1.1.2BIOS在内存中加载中断向量表和中断服务程序 1.2加载操作系统内核程序并为保护模式做准备 1.2.1加载第一部分内核代码引导程序(bootsect) 1.2.2加载第二部分内核代码setup 1.2.3加载第三部分内核代码system模块 1.3开始向32位

2、模式转变,为main函数的调用做准备 1.3.1关中断并将system移动到内存地址起始位置0x00000 1.3.2设置中断描述符表和全局描述符表 1.3.3打开A20,实现32位寻址 1.3.4为保护模式下执行head.s做准备 1.3.5head.s开始执行 2.从main到怠速 2.1 设备环境初始化及激活进程0 2.1.1 与建立人机交互界面相关的外设的中断服务程序挂接 2.1.2初始化进程0 2.1.3初始化硬盘 2.1.4开启中断 2.2 进程1的创建及执行 2.2.1 进程0创建进程1 2.2.2 内核第一次做进程调度 2.2.3轮转到进程1执行 2.3 进程2的创建及执行 2

3、.3.1、打开终端设备文件及复制文件句柄 2.3.2、进程1创建进程2并切换到进程2 2.3.3、加载shell程序 2.3.4、实现系统怠速 1.从开机加电到执行main函数之前的过程从开机到main函数的执行分三步完成,目的是实现从启动盘加载操作系统程序,完成执行main函数所需要的准备工作。第一步,启动BIOS,准备实模式下的中断向量表和中断服务程序;第二步,从启动盘加载操作系统程序到内存,加载操作系统程序的工作就是利用第一步中准备的中断服务程序实现的;第三步,为执行32位的main函数做过渡工作。本章将详细分析这三步在计算机中是如何完成的,以及每一步在内存中都做了些什么。1.1启动BI

4、OS,准备实模式下的中断向量表和中断服务程序问题:在RAM中什么程序也没有的时候,谁来完成加载软盘中操作系统的任务呢?答案是:BIOS。1.1.1BIOS的启动原理从硬件角度看,Intel 80x86系列的CPU可以分别在16位实模式和32位保护模式下运行。为了兼容,也为了解决最开始的启动问题,Intel 将所有80x86系列的CPU,包括最新型号的CPU的硬件都设计为加电即进入16位实模式状态运行。同时,还有一点非常关键的是,将CPU硬件逻辑设计为加电瞬间强行将CS的值置为0xF000、IP的值置为0xFFF0,这样CS:IP就指向0xFFFF0这个地址位置。1.1.2BIOS在内存中加载中

5、断向量表和中断服务程序BIOS程序在内存最开始的位置(0x00000)用1 KB的内存空间(0x000000x003FF)构建中断向量表,在紧挨着它的位置用256字节的内存空间构建BIOS数据区(0x004000x004FF),并在大约57 KB以后的位置(0x0E05B)加载了8 KB左右的与中断向量表相应的若干中断服务程序。中断向量表中有256个中断向量,每个中断向量占4字节,其中两个字节是CS的值,两个字节是IP的值。每个中断向量都指向一个具体的中断服务程序。1.2加载操作系统内核程序并为保护模式做准备从现在开始,就要执行真正的boot操作了,即把软盘中的操作系统程序加载至内存。对于Li

6、nux 0.11操作系统而言,计算机将分三批逐次加载操作系统的内核代码。第一批由BIOS中断int0x19把第一扇区bootsect的内容加载到内存;第二批、第三批在bootsect的指挥下,分别把其后的4个扇区和随后的240个扇区的内容加载至内存。1.2.1加载第一部分内核代码引导程序(bootsect)经过执行一系列BIOS代码之后,计算机完成了自检等操作(这些和我们讲的启动操作系统没有直接的关系,读者不必关心)。由于我们把软盘设置为启动设备,计算机硬件体系结构的设计与BIOS联手操作,会让CPU接收到一个int 0x19中断。CPU接收到这个中断后,会立即在中断向量表中找到int 0x1

7、9中断向量。接下来,中断向量把CPU指向0x0E6F2,这个位置就是int0x19相对应的中断服务程序的入口地址。这个中断服务程序的作用就是把软盘第一扇区中的程序(512 B)加载到内存中的指定位置。这个中断服务程序的功能是BIOS事先设计好的,代码是固定的,与Linux操作系统无关。无论Linux 0.11的内核是如何设计的,这段BIOS程序所要做的就是“找到软盘”并“加载第一扇区”,其余的它什么都不知道,也不必知道。按照这个简单、“生硬”的规则,int 0x19中断向量所指向的中断服务程序,即启动加载服务程序,将软驱0号磁头对应盘面的0磁道1扇区的内容复制至内存0x07C00处。1.2.2

8、加载第二部分内核代码setupbootsect对内存的规划BIOS已经把bootsect也就是引导程序载入内存了,现在它的作用就是把第二批和第三批程序陆续加载到内存中。为了把第二批和第三批程序加载到内存中的适当位置,bootsect首先做的工作就是规划内存。通常,我们是用高级语言编写应用程序的,这些程序是在操作系统的平台上运行的。我们只管写高级语言的代码、数据。至于这些代码、数据在运行的时候放在内存的什么地方,是否会相互覆盖,我们都不用操心,因为操作系统和高级语言的编译器替我们做了大量的看护工作,确保不会出错。现在我们讨论的是,操作系统本身使用的是汇编语言,没有高级语言编译器替操作系统提供保障

9、,只有靠操作系统的设计者把内存的安排想清楚,确保无论操作系统如何运行,都不会出现代码与代码、数据与数据、代码与数据之间相互覆盖的情况。为了更准确地理解操作系统的运行机制,我们必须清楚操作系统的设计者是如何规划内存的。在实模式状态下,寻址的最大范围是1 MB。这些源代码的作用就是对后续操作所涉及的内存位置进行设置,包括将要加载的setup程序的扇区数(SETUPLEN)以及被加载到的位置(SETUPSEG);启动扇区被BIOS加载的位置(BOOTSEG)及将要移动到的新位置(INITSEG);内核(ker-nel)被加载的位置(SYSSEG)、内核的末尾位置(ENDSEG)及根文件系统设备号(R

10、OOT_DEV)。设置这些位置就是为了确保将要载入内存的代码与已经载入内存的代码及数据各在其位,互不覆盖,并且各自有够用的内存空间。下面,bootsect程序要执行它的第二步工作:将setup程序加载到内存中。加载setup这个程序,要借助BIOS提供的int 0x13中断向量所指向的中断服务程序(也就是磁盘服务程序)来完成。执行int 0x13指令,产生0x13中断,通过中断向量表找到这个中断服务程序,将软盘第二扇区开始的4个扇区,即setup.s对应的程序加载至内存的SE-TUPSEG(0x90200)处。复制后的boot-sect的起始位置是0x90000,占用512字节的内存空间。不难

11、看出0x90200紧挨着bootsect的尾端,所以bootsect和setup是连在一起的。现在,操作系统已经从软盘中加载了5个扇区的代码。等bootsect执行完毕后,setup这个程序就要开始工作了。1.2.3加载第三部分内核代码system模块接下来,bootsect程序要执行第三批程序的载入工作,即将系统模块载入内存。bootsect借着BIOS中断int 0x13,将240个扇区的system模块加载进内存。加载工作主要是由bootsect调用read_it子程序完成的。到此为止,第三批程序已经加载完毕,整个操作系统的代码已全部加载至内存。bootsect的主体工作已经做完了。下面

12、要通过执行“jmpi 0, SETUPSEG”这行语句跳转至0x90200处,就是前面讲过的第二批程序setup程序加载的位置。CS:IP指向setup程序的第一条指令,意味着由setup程序接着bootsect程序继续执行。setup程序现在开始执行。它做的第一件事情就是利用BIOS提供的中断服务程序从设备上提取内核运行所需的机器系统数据,其中包括光标位置、显示页面等数据,这些机器系统数据被加载到内存的0x900000x901FC位置。图1-15标出了其内容及准确的位置。这些数据将在以后main函数执行时发挥重要作用。到此为止,操作系统内核程序的加载工作已经完成。接下来的操作对Linux 0

13、.11而言具有战略意义。系统通过已经加载到内存中的代码,将实现从实模式到保护模式的转变,使Linux 0.11真正成为“现代”操作系统。1.3开始向32位模式转变,为main函数的调用做准备接下来,操作系统要使计算机在32位保护模式下工作。这期间要做大量的重建工作,并且持续工作到操作系统的main函数的执行过程中。在本节中,操作系统执行的操作包括打开32位的寻址空间、打开保护模式、建立保护模式下的中断响应机制等与保护模式配套的相关工作、建立内存的分页机制,最后做好调用main函数的准备。1.3.1关中断并将system移动到内存地址起始位置0x00000如图所示,这个准备工作先要关闭中断,即将

14、CPU的标志寄存器(EFLAGS)中的中断允许标志(IF)置0。这意味着,程序在接下来的执行过程中,无论是否发生中断,系统都不再对此中断进行响应,直到main函数中能够适应保护模式的中断服务体系被重建完毕才会打开中断,而那时候响应中断的服务程序将不再是BIOS提供的中断服务程序,取而代之的是由系统自身提供的中断服务程序。下面,setup程序做了一个影响深远的动作:将位于0x10000的内核程序复制至内存地址起始位置0x00000处!这样做能取得“一箭三雕”的效果:1)废除BIOS的中断向量表,等同于废除了BIOS提供的实模式下的中断服务程序。2)收回刚刚结束使用寿命的程序所占内存空间。3)让内

15、核代码占据内存物理地址最开始的、天然的、有利的位置。1.3.2设置中断描述符表和全局描述符表setup程序继续为保护模式做准备。此时要通过setup程序自身提供的数据信息对中断描述符表寄存器(IDTR)和全局描述符表寄存器(GDTR)进行初始化设置。GDT(Global Descriptor Table,全局描述符表),在系统中唯一的存放段寄存器内容(段描述符)的数组,配合程序进行保护模式下的段寻址。它在操作系统的进程切换中具有重要意义,可理解为所有进程的总目录表,其中存放每一个任务(task)局部描述符表(LDT,Local Descriptor Table)地址和任务状态段(TSS,Tas

16、kStructure Segment)地址,完成进程中各段的寻址、现场保护与现场恢复。IDT(Interrupt Descriptor Table,中断描述符表),保存保护模式下所有中断服务程序的入口地址,类似于实模式下的中断向量表。1.3.3打开A20,实现32位寻址下面是标志性的动作打开A20!打开A20,意味着CPU可以进行32位寻址,最大寻址空间为4 GB。打开A20现在看来,Linux 0.11还显得有些稚嫩,最大只能支持16 MB的物理内存,但是其线性寻址空间已经是不折不扣的4 GB。1.3.4为保护模式下执行head.s做准备setup程序将CPU工作方式设为保护模式。将CR0寄

17、存器第0位(PE)置1,即设定处理器工作方式为保护模式。1.3.5head.s开始执行head程序除了做一些调用main的准备工作之外,还做了一件对内核程序在内存中的布局及内核程序的正常运行有重大意义的事,就是用程序自身的代码在程序自身所在的内存空间创建了内核分页机制,即在0x000000的位置创建了页目录表、页表、缓冲区、GDT、IDT,并将head程序已经执行过的代码所占内存空间覆盖。这意味着head程序自己将自己废弃,main函数即将开始执行。这些工作完成后,内存中的布局如图所示。可以看出,只有184字节的剩余代码。由此可见,在设计head程序和system模块时,其计算是非常精确的,对

18、head.s的代码量的控制非常到位。开机时的16位实模式与main函数执行需要的32位保护模式之间有很大的差距,这个差距谁来填补? head.s做的就是这项工作。这期间,head程序打开A20,打开pe、pg,废弃旧的、16位的中断响应机制,建立新的32位的IDT这些工作都做完了,计算机已经处在32位的保护模式状态了,调用32位main函数的一切条件已经准备完毕,这时顺理成章地调用main函数。后面的操作就可以用32位编译的main函数完成。至此,Linux 0.11内核启动的一个重要阶段已经完成,接下来就要进入main函数对应的代码了。特别需要提示的是,此时仍处在关闭中断的状态!2.从mai

19、n到怠速系统达到怠速状态前所做的一切准备工作的核心目的就是让用户程序能够以“进程”的方式正常运行。能够实现这一目的的标准包括三方面的内容:1)用户程序能够在主机上进行运算;2)能够与外设进行交互;3)能够让用户以它为媒介进行人机交互。2.1 设备环境初始化及激活进程02.1.1 与建立人机交互界面相关的外设的中断服务程序挂接Linus在操作系统源代码中本来设计了chr_dev_init()函数,明显是要用这个函数初始化字符设备,但我们可以看到这是一个空函数。Linus又设计了tty_init()函数,内容就是初始化字符设备。有人解释tty是teletype。字符设备的初始化为进程与串行口(可以

20、通信、连接鼠标)、显示器以及键盘进行I/O通信准备工作环境,主要是对串行口、显示器、键盘进行初始化设置,以及与此相关的中断服务程序与IDT挂接。2.1.2初始化进程0进程0是Linux操作系统中运行的第一个进程,也是Linux操作系统父子进程创建机制的第一个父进程。下面讲解的内容对进程0能够在主机中正常运算的影响最为重要和深远,主要包含如下三方面的内容。1)系统先初始化进程0。进程0管理结构task_struct的母本(init_task = INIT_TASK,)已经在代码设计阶段事先设计好了,但这并不代表进程0已经可用了,还要将进程0的task_struct中的LDT、TSS与GDT相挂接

21、,并对GDT、task64以及与进程调度相关的寄存器进行初始化设置。2)Linux 0.11作为一个现代操作系统,其最重要的标志就是能够支持多进程轮流执行,这要求进程具备参与多进程轮询的能力。系统这里对时钟中断进行设置,以便在进程0运行后,为进程0以及后续由它直接、间接创建出来的进程能够参与轮转奠定基础。3)进程0要具备处理系统调用的能力。每个进程在运算时都可能需要与内核进行交互,而交互的端口就是系统调用程序。系统通过函数set_system_gate将system_call与IDT相挂接,这样进程0就具备了处理系统调用的能力了。这个system_call就是系统调用的总入口。进程0只有具备了

22、以上三种能力才能保证将来在主机中正常地运行,并将这些能力遗传给后续建立的进程。2.1.3初始化硬盘硬盘的初始化为进程与硬盘这种块设备进行I/O通信建立了环境基础。在hd_init()函数中,将硬盘请求项服务程序do_hd_request()与blk_dev控制结构相挂接,硬盘与请求项的交互工作将由do_hd_request()函数来处理,然后将硬盘中断服务程序hd_interrupt()与IDT相挂接,最后,复位主8259A int2 的屏蔽位,允许从片发出中断请求信号,复位硬盘的中断请求屏蔽位(在从片上),允许硬盘控制器发送中断请求信号。2.1.4开启中断现在,系统中所有中断服务程序都已经和

23、IDT正常挂接。这意味着中断服务体系已经构建完毕,系统可以在32位保护模式下处理中断,重要意义之一是可以使用系统调用。可以开启中断了!2.2 进程1的创建及执行现在,计算机中已经有了一个名副其实的、3特权级的进程进程0。下面我们要详细讲解进程0做的第一项工作创建进程1。2.2.1 进程0创建进程1进程0作为父进程调用fork函数创建第一个子进程进程1。执行sys_fork(),在task64中为进程1申请一个空闲位置并获取进程号。进程0将在copy_process()函数中做非常重要的、体现父子进程机制的工作:(1)为进程1创建tast_struct,将进程0的tast_struct内容复制给

24、进程1;(2)为进程1的tast_struct、tss做个性化设置;(3)为进程1创建第一个页表,将进程0的页表内容赋给这个页表;(4)进程1共享进程0的文件;(5)设置进程1的GDT项;(6)最后将进程1设置为就绪状态,使其可以参与进程间的轮转2.2.2 内核第一次做进程调度产生进程切换的两种情况:(1)允许进程运行的时间结束;(2)进程的运行停止。进入sys_pause()函数后,将进程0设置为可中断等待状态,然后调用schedule()函数进行进程切换。2.2.3轮转到进程1执行进程1为安装硬盘文件系统做准备:(1)根据机器系统数据设置硬盘参数;(2)读取硬盘引导块;(3)从引导块中获取

25、信息。进程1格式化虚拟盘并更换根设备为虚拟盘:格式化虚拟盘使之成为块设备进程1在根设备上加载根文件系统:操作系统的文件系统大致分为两类:一部分在操作系统内核中,另一部分在硬盘、软盘、虚拟盘中。2.3 进程2的创建及执行现在已经有了进程0、进程1。下面主要讲进程1如何创建进程2的过程,以及进程2的执行,最终shell进程开始执行,整个boot工作完成,实现系统怠速。2.3.1、打开终端设备文件及复制文件句柄(1)打开标准输入设备文件(2)打开标准输出、标准错误输出设备文件:复制文件句柄的方法实现2.3.2、进程1创建进程2并切换到进程2进程1调用fork()函数,创建进程2,schedual()函数切换到进程2。进程2的加载是从硬盘中加载。2.3.3、加载shell程序(1)关闭标准输入设备文件,打开rc文件(2)检测shell文件(3)为shell程序的执行做准备(4)执行shell程序2.3.4、实现系统怠速(1)创建update进程:主要任务是将缓冲区中的数据同步到外设(软盘、硬盘等)上,为了提高效率。(2)切换到shell程序执行(3)重建shell:实现系统怠速后,操作系统用户将通过shell进程提供的平台与计算机进行交互。

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2