首页
学习
活动
专区
圈层
工具
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

基于 Linux 0.11 讲解 Linux 操作系统的启动原理

在 Linux 服务器没有通电的时候,操作系统还只是躺在硬盘启动区中的一段程序,CPU 没有工作,内存也没有启动。但是在你按下开机键后,Linux 服务器内部就开始变得热闹了起来。...全书共 400 多页,250 多张精美的图解,五大部分,从头到尾把 Linux 0.11 全部核心代码讲述的一清二楚 当你按下电源后,在主板上提前写死的固件程序 BIOS 会将硬盘启动区中的 512...接着除了引导区的 512 字节外的 200 多个扇区的内核代码都会被加载到内存中。 再接着内核会设置全局描述符表 GDT 也会被初始化。...全局描述符表入口位置保存在 gdtr 寄存器中,是为了后面逻辑地址转化成物理地址时使用的。接着进入保护模式、开启分页机制后会进入到内核的 main 函数中。 是的,内核也有一个 main 函数。...并设置了时钟中断,将来用作触发调度。 硬盘初始化后,内核打开允许硬盘控制器发送中断请求信号。 ...... 上面描述的这些都是操作系统的第 0 号内核线程处理的。

48411

操作系统开发:编写开机引导

接着BIOS将会通过自身的代码对硬件进行自检测,在初始化硬件后,则开始向内存0x000-0x3ff中初始化数据结构以及拷贝中断向量表,紧接着BIOS将会通过调用int 19h中断,此中断用以检测计算机中的硬盘...由于全局描述符表GDT很大,所以默认将其放在了内存中,由GDTR寄存器指向它,GDTR是个48位的寄存器,通常使用lgdtr指令操作,控制该寄存器。...这样,段寄存器中保存的再也不是段基址了,里面保存的内容叫 段选择子(selector) 该选择子其实就是个数,用这个数来索引全局描述符表中的段描述符,如果把全局描述符表当成数组,那么选择子就是数组的下标...GDT 全局描述符表 全局描述符表GDT是保护模式下内存段的登记表,这是不同于实地址模式下的显著特征。 局部描述符表LDT是CPU厂商为了在硬件层面支持多任务的一个表,当今操作系统不使用。...段选择子: 保护模式下段寄存器中存储的就是段选择子,选择子是一个索引值,用此索引值在段描述符表中索引相应的段描述符,这样,便可以在段描述符中得到了内存段的起始地址和段界限值等相关信息。

75030
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    xv6 启动理论部分

    32 位,段寄存器没变 仍然采用 $段基址(选择子):段内偏移$ 地址的访问策略,但引入了全局描述符表,由此间接安全的访问内存 段寄存器里面放的不再是段基址,而是选择子(可见部分),要从段描述符中(或者段寄存器的不可见的缓存部分...)获取段基址 相对于实模式,基本上弥补了其缺点,便是保护模式的优点,再此便不细说了 全局描述符表 GDT 为了安全地进行内存访问,引入了全局描述符表,使得 $段基址 : 段内偏移$ 的访问策略从实模式下对物理地址的直接映射变为保护模式下对全局描述符表的间接映射...: 利用键盘控制器 通过 BIOS 中断 通过系统端口 0x92 这里就不细说了,后面 xv6 会讲述利用键盘控制器打开 A20 构建加载GDT GDT 是硬件支持的一个数据结构,专门有个寄存器 GDTR...BIOS 程序不需要由谁加载,本身便固化在ROM只读存储器中 开机的一瞬间 cs:ip 便被初始化为0xf000 : 0xfff0。...BIOS 程序做了以下事情: POST 自检,检验主板,内存,各类外设 对设备进行初始化 建立中断表、构建 BIOS 数据区、加载中断服务程序 权力交接给 MBR BIOS 最后一项工作便是加载启动盘最开始那个扇区里面的引导程序到

    43800

    操作系统启动顺序bios在哪里寻址机制bootloader结构建立段机制使能保护模式

    bios在哪里 bios是固化在内存EPROM中的,断电不会丢失(非易失性),这样biod的地址是固定的,因为在cpu第一次加电了之后,寄存器就会有缺省的初始值,所以bios地址=寻址寄存器的缺省值就好啦...因为内存很大,而且在一段时间内操作的内存具有空间局部性,所以可以将内存分为一段一段由段寄存器来定位,这一段的内存中再由指令指针来定位到具体的代码、数据 段寄存器: CS——code segment,代码段寄存器...因为实模式只有20位寻址,所以最大可调用的空间只有1M bios bios是负责做硬件自检并初始化以及将bootloader加载到内存中 要保证硬盘、内存...在后续工作中不会出错。...bootloader bootloader要完成使能保护模式(实模式——>保护模式)、建立段机制以及加载操作系统 bootloader结构 bootloader在硬盘中的第一个扇区也叫主引导扇区,一个扇区是...段机制就是中间做了一层映射,CS先定位到GDT(全局描述表)相应的段描述符,再从段描述符中找到段的起始地址,与IP组成物理地址。

    1.3K100

    操作系统之x86架构下的bootloader

    bootloader主要做四件事,1.开启A20地址线;2.探测内存,把内存相关信息告诉内核;3.初始化全局描述符表,开启分段机制,进入保护模式;4.把操作系统内核从磁盘加载到内存指定位置,跳转到内核,...0x15中断获取内存信息,命令字0xe820....jmp finish_probe cont: addw $20, %di incl 0x6000 cmpl $0, %ebx jnz start_probe 3.初始化全局描述符表...分段寻址模式,(1)指令寻址: cs寄存器包含了当前段在全局描述符表中的偏移和rpl请求特权级,通过cs找到段描述符,从段描述符取出基地址+ip寄存器的偏移量,得到线性地址。...(2)数据寻址:通过ds ss es寄存器找到全局描述符表中的段描述符,然后拼接地址。

    63520

    中断描述符表

    Hi~朋友,码字不易,点点关注呗 摘要 中断描述符表 中断描述符寄存器 中断细节 中断错误码 中断描述符表 什么是中断描述符表? 中断描述符表是保护模式下用于存储中断处理程序的数据结构。...CPU在接收到中断时,会根据中断向量在中断描述符表中检索对应的描述符。 中断描述符表中的描述符有哪些类型?...任务门可以存在于全局描述符GDT、局部描述符表LDT以及中断描述符表IDT中。...通过lidt 48位内存数据指令便可将中断描述符表的信息加载到IDTR寄存器中。 中断细节 中断处理过程包含哪两部分?...将门描述符中的目标代码段描述符选择子加载到代码段寄存器CS中,把门描述中中断处理程序的偏移地址加载到EIP,便开始执行中断程序。 如何确定使用新栈还是旧栈?

    86540

    一文详解 32 位保护模式与内存分段机制

    实地址模式 此前的文章中,我们在系统启动时,通过触发 BIOS 中断,实现了在屏幕上显示出“Hello World my OS!”。 计算机是如何启动的?...但我们已经看到,在实地址模式下,应用程序可以读取、修改整个内存空间,这让 CPU 必须在一个进程完全运行结束后才能够进行内存的清理并加载新的程序,否则多个程序会在内存使用上发生冲突。...分段寻址过程 IA-32 CPU 中存在一个 48 位的分段描述符表寄存器 GDTR,他存储了 32 位的分段描述符表起始地址与 16 位的分段描述符表偏移量,因此只要读取分段描述符表寄存器,就可以在内存中找到对应的分段描述符表...全局描述符表寄存器 GDTR 下图展示了 48 位全局描述符表寄存器 GDTR 的存储结构: 显而易见,GDTR 定义了全局描述符表 GDT 的起始地址与界限,由于 GDTR 中 GDT 界限为 16...局部描述符表是全局描述附表的下一级,在内存中,存在着很多个 LDT,每个 LDT 对应全局描述附表中的一个描述符,这个描述符描述了局部描述符表的起始地址与界限,而这个 LDT 中则对当前段区域进行了更细粒度的段拆分

    1.4K31

    MIT 6.828 操作系统工程 lab3A:用户环境和异常处理

    inc/trap.h 中定义的该结构在该环境不运行时(即,在内核或其他环境正在运行时)保存该环境的已保存寄存器值。...像Unix进程一样,JOS环境将 “线程” 和 “地址空间” 的概念结合在一起。线程主要由保存的寄存器(env_tf字段)定义,地址空间由 env_pgdir 指向的页目录和页表定义。...这两个结构都在一个结构中保留环境(即进程)的用户模式寄存器状态Trapframe 。在JOS中,各个环境不像xv6中的进程那样具有自己的内核堆栈。...因为我们还没有文件系统,所以我们将设置内核以加载嵌入在内核本身中的静态二进制映像。JOS将此二进制文件作为ELF可执行映像嵌入内核。...在x86上,两种机制可以共同提供这种保护: 中断描述符表 任务状态段 异常和中断的类型 x86处理器可以在内部生成的所有同步异常都使用0到31之间的中断向量,因此映射到IDT条目0-31。

    70920

    ucoreOS_lab1 实验报告

    为了做好这一步,它需要干如下一些事情: 开启A20 初始化GDT表(全局描述符表) 使能和进入保护模式 为何开启A20,以及如何开启A20 在i8086时代,CPU的数据总线是16bit,地址总线是...解决的方法就是把这些长度为64-bit的段描述符放入一个数组中,而将段寄存器中的值作为下标索引来间接引用(事实上,是将段寄存器中的高13 -bit的内容作为索引)。这个全局的数组就是GDT。...另外,每一个LDT自身作为一个段存在,它们的段描述符被放在GDT中。 IA-32为LDT的入口地址也提供了一个寄存器LDTR,因为在任何时刻只能有一个任务在运行,所以LDT寄存器全局也只需要有一个。...(如除零错、地址访问越界)所引起的内部事件称作同步中断,也称内部中断 在程序中使用请求系统服务的系统调用而引发的事件,称作陷入中断,也称软中断,系统调用简称trap 中断描述符表(也可简称为保护模式下的中断向量表...中断处理函数在退出的时候会把这些参数全部 pop 回寄存器中,于是我们可以趁它还在栈上的时候修改其值,在退出中断处理的时候相应的段寄存器就会被更新。

    1.8K20

    操作系统(3)实验相关原理——bootloader启动uCore

    这么做的原因是BIOS只能加载一个扇区,所以只能通过bootloader来加载系统。 段机制 这边uCore没有实现段机制,因为可以通过页机制来很方便地实现。...段描述符表用来查找段描述符,index用的是段寄存器的内容,段描述符最终就相当于是一个起始地址。上图中线性地址就等同于物理地址(因为还没启动页机制)。...段描述符表相当于是一个数组,这个数组由操作系统生成,我们称之为GDT,全局描述符表。GDT由Bootloader建立。CPU内部的GDTR这个寄存器用来保存GDT。...IDT中每一项称为中断门或者陷阱门(和之前的全局描述符表类似,也是个数组),通过中断号来选中IDT中的陷阱门,通过这个陷阱门/中断门可以获得陷阱门/中断门相关的段的选择子(类似段机制的选择子和段类偏移)...系统调用 小结 上图中GCC内联汇编就是在C里面嵌入汇编代码,没什么特殊含义。 后面会有一篇关于实验的博文,今天就写到这里。

    82530

    Linux内核17-硬件如何处理中断和异常

    那么,剩下的工作就是内核的了,内核使用一个中断描述符表(IDT),记录每个中断或者异常编号以及相应的处理函数。那么,收到中断信号后,将相应的处理函数的地址加载到eip寄存器中执行即可。...如果发生中断,控制单元就会做如下处理: 确定中断或异常的编号N; 读取IDT表中的第N项;(在后面的描述中,假设包含的是中断门或陷阱门) 获取GDT的基地址,遍历GDT找到IDT表第N项中的段选择器标识的段描述符...对于可编程异常,还会做进一步的安全检查:比较当前特权等级(CPL)和IDT表中包含的描述符的DPL,如果DPL小于CPL,则产生通用保护的异常。...读取tr寄存器,访问运行中的进程的TSS段; 使用新特权等级对应的堆栈段和堆栈指针加载ss和esp寄存器;(这些值存储在TSS中) 在新的堆栈中,保存旧任务的ss和esp寄存器值。...,将其保存在堆栈中; 根据IDT表中的第N项内容,加载cs和eip寄存器。

    2.2K10

    操作系统的启动

    建立好中断向量表以及其他操作后,BIOS会触发一个int0x19中断,CPU接收到这个中断后,会去内存的BIOS中断向量表里找到int0x19这个中断的中断服务程序(内存位置在0x0E6F2),这个中断服务程序的功能就是把磁盘里的第一个扇区...加载进来后,setup会再次调整内存规划,然后会使用int0x13中断向量继续加载240个扇区的内容,也就是system模块。...setup还会做一些设置,例如关中断,设置中断描述符表和全局描述符表,打开A20实现32位寻址,对编程中断控制器8259A进行重编程,建立保护模式下的中断机制等等,为内核main函数的调用做准备。...此时内存的视图如下: linux内存.png所以,我们可以知道,当BIOS运行后,会通过int0x19中断读取第一扇区的内容,BIOS并不管这个扇区里是否有内容。...所以这个第一扇区是至关重要的,是BIOS与系统的协议。 所以,我们可以知道,当BIOS运行后,会通过int0x19中断读取第一扇区的内容,BIOS并不管这个扇区里是否有内容。

    1.5K30

    ucore-lab1

    系统启动及中断 bios提供了基本的i/o功能 cpu加电后执行ROM里的初始化代码: 图片 从硬盘/网络启动是由bios决定,bios加载程序到磁盘的引导扇区,跳转到cs:ip=0000:7c00.../dos中断的区别 bios/dos建立在实模式下,他们建立的中断调用都采用中断向量表,linux则是在进入保护模式后才建立中断例程,通过中断描述符表idt实现中断 文件 os通过文件系统的magic...全局描述符表(GDT)是一个保存多个段描述符的“数组”,其起始地址保存在全局描述符表寄存器GDTR中。...选择子可以做为指针变量的一部分,从而对应用程序员是可见的,但是一般是由连接加载器来设置的。 段选择子结构 索引(Index):在描述符表中从8192个描述符中选择一个描述符。...接下来就是加载gdt这个全局描述符表,最后重新使用32位模式,重新切回到保护模式。

    1.9K30

    进入Linux内核前的准备

    加载启动区 在按下开机键后,主板上写死的Bios程序会加载硬盘的启动区,也就是BIOS会将把硬盘上启动区代码这段512个Byte大小的数据,复制到内存中0x7c00这个位置并且跳转到这个位置开始执行这段程序...在保护模式下,段寄存器(ex ds,ss,cs..)里面存储的是段选择子,段选择子去全局描述符表GDT中寻找段描述符,从中取出段基址,段基址加上偏移地址就是实际访问的物理地址。...全局描述符表是让段选择子去找段描述符用的,而中断描述符表使用来在发生中断时,CPU拿中断号去中断描述符表中寻找终端处理程序的地址,找到后就跳到想要的中断程序中去执行。...继续看head.s,两个call语句设置了中断描述符表IDT和全局描述符表GDT,然后后面又是重新执行了一遍前面的代码,为什么要重新设置段寄存器的值呢?...CPU在得到线性地址后,将线性地址拆分为10b:10b:12b,高10位表示页目录表中的页目录项,页目录项的值拼接中间10位地址后,去页表中找对应的页表项,再拼接上低12位偏移地址,就可以在页表项中访问对应的物理地址

    6K20

    bootsect及setup

    CPU执行的第一条指令的地址 image.png BIOS程序在内存中加载中断向量表和中断服务程序 ?...调用INT 0x19中断,将软盘第一扇区(0面0磁道1扇区)的512字节即bootsect.s加载到内存0x07C00处 ?...调用INT 0x13中断,将setup.s对应的程序加载到0x90200处,共四个扇区2K 再通过INT 0x13中断,将system加载到0x10000 检查根设备 然后跳到setup.s的第一行指令...可见,bootsect主要完成的是搬运加载工作 setup setup程序的第一件事是利用BIOS中断服务程序将机器系统数据加载在原bootsect的位置(覆盖),0x90000~0x901FD,在setup...设置全局描述符表(将来存放LDT和TSS)以及中断描述符表,GDT -> GDTR,IDT -> IDTR,注:setup.s从0x92000开始,gdt段内偏移相对0x90000要加上512 ?

    1.2K30

    GDT,LDT,GDTR,LDTR

    GDT,LDT,GDTR,LDTR 前言 全局描述符表GDT 局部描述符表LDT 中断描述符表IDT 段选择子 任务寄存器TR 实例 1:访问GDT 2:访问LDT ---- 前言 所谓工作模式,是指CPU...---- 全局描述符表GDT 全局描述符表GDT(Global Descriptor Table)在整个系统中,全局描述符表GDT只有一张,GDT可以被放在内存的任何位置,但CPU必须知道GDT的入口,...全局描述符表在系统中只能有一个,且可以被每一个任务所共享.任何描述符都可以放在GDT中,但中断门和陷阱门放在GDT中是不会起作用的.能被多个任务共享的内存区就是通过GDT完成的, GDTR寄存器中的基地址指定...指令LGDT和SGDT分别用于加载和保存GDTR寄存器的内容。在机器刚加电或处理器复位后,基地址被默认地设置为0,而长度值被设置成0xFFFF。在保护模式初始化过程中必须给GDTR加载一个新值。...指令LIDT和SIDT分别用于加载和保存IDTR寄存器的内容。在机器刚加电或处理器复位后,基地址被默认地设置为0,而长度值被设置成0xFFFF。

    1.4K10

    Linux内核19-中断描述符表IDT的初始化

    而Linux使用中断描述符表IDT记录管理所有的中断和异常。那么,首先,Linux内核应该把IDT的起始地址写入idtr寄存器,然后初始化所有的表项。这一步在初始化系统时完成。...中断、陷阱和系统门 在之前的文章中,我们已经介绍过,Intel提供了三种类型的中断描述符:任务,中断和陷阱门描述符。Linux的分类有些不同,它们如下所示: 中断门 和Intel的中断门相同。...第一次是在BIOS程序中,此时CPU还工作在实模式下。一旦Linux启动,IDT会被搬运到RAM的受保护区域并被第二次初始化,因为Linux不会使用任何BIOS程序。...IDT结构被存储在idt_table表中,包含256项。idt_descr变量存储IDT的大小和它的地址,在系统的初始化阶段,内核用来设置idtr寄存器,专用汇编指令是lidt。...,DPL=0 */ lea idt_table, %edi /* 加载idt表的地址到寄存器edi中 */ mov $256, %ecx rp_sidt: movl %eax

    1K10

    实战分页机制实现 -- 通过实际内存大小动态调整页表个数

    通过 BIOS 中断获取内存信息 我们曾经通过 BIOS 的 10H 硬件中断实现向显示器输出一行文字。 计算机是如何启动的?...原理 用于获取内存信息的 10H 中断将内存信息拼装为一个 20 个字节的数据结构 — 地址范围描述符结构,写入到指定的内存中。...每一次中断生成一个描述符结构,用来表示一段连续可用的内存,经过若干次中断调用,即可获取整个内存中若干段的可用内存。 2.2....INT 15H 中断完成后寄存器的值 EFLAGS — EFLAGS 的 CF 位表示中断执行是否出错,位 0 表示没有出错,为 1 表示出错 EAX — 0534D4150h ECX — BIOS 实际写入字节数...打印一个 dword 中的数字 在 32 位系统中,打印一个 32 位的数字是最为常用的功能,也是我们本次程序中所必须使用的。

    90420
    领券