• 本文主要介绍了Linux操作系统启动过程,对于各个阶段的工作内容进行了说明。

    Linux操作系统的启动过程一般分为四个阶段:

    • BIOS启动引导阶段;
    • GRUB启动引导阶段;
    • 内核阶段;
    • init初始化阶段。

    BIOS启动引导阶段

    系统上电开机后,主板BIOS运行POSTPower on self test)代码,检测系统外围一些设备(如:CPU、内存、显卡、I/O、键盘鼠标等),当设备检测通过后,系统开始启动自举程序,根据在BIOS中设置的启动顺序搜索启动驱动器(比如硬盘、光驱、网络服务器等),并获取第一个启动设备的代号,读取第一个启动设备的MBR的引导加载程序(即lilo、grub、spfdisk等)的启动信息,MBR中装载启动引导管理器(GRUB)并运行该启动引导管理。至此进入GRUB启动引导阶段。

    GRUB启动引导阶段

    主要操作是装载stage1,装载stage1.5,装载stage2

    然后读取/boot/grub.conf文件显示启动菜单,装载所选的kernelinitrd文件到内存中。

    BIOS通过下面两种方法之一来传递引导记录:

    • 将控制权传递给initial program loaderIPL),该程序安装在磁盘主引导记录(MBR)中  
    • 将控制权传递给initial program loaderIPL),该程序安装在磁盘分区的启动引导扇区中

    上面两种方法比较后,无论上面的哪种情况中,IPL都是MBR的一部分,都需要MBR的参与。

    IPLGRUB阶段的第一个部分(stage1),他的作用就是定位和装载GRUB的第二个部分(stage2);因为stage1没有文件系统识别能力,所以具有文件系统识别能力的stage1.5成为stage1stage2之间连接的桥梁,这样GRUB才有能力去访问/boot分区/boot/grub目录下的 stage2文件,将stage2载入内存并执行。

    stage2对启动系统起关键作用,该部分提供了GRUB启动菜单和交互式的GRUBshell

    启动菜单在启动时候通过/boot/grub/grub.conf文件所定义的内容生成。

    在启动菜单中选择了kernel之后,GRUB会负责解压和装载kernel image并且将initrd装载到内存中,最后GRUB初始化kernel启动代码,完成之后后续的引导权被移交给kernel

    内核阶段

    操作系统的核心是放在文件系统中的,要想正确加载核心就必须提前识别文件系统。

    要想加载linux的核心就必须能识别linux的文件系统,核心文件一般会放在/boot/vmlinuz。

    系统启动的控制权移交给kernelKernel会立即初始化系统中各设备并做相关配置工作,其中包括CPUI/O、存储设备等。

    配置过程中进行设备驱动加载的时候,一部分设备的驱动编入Linux Kernel中,Kernel会调用这部分驱动初始化相关设备;另外有一部分设备驱动并没有编入Kernel,而是作为模块形式放在initrd中。

    initrd是一种基于内存的文件系统,启动过程中,系统在访问真正的根文件系统时,会先访问initrd文件系统。

    initrd中的内容打开来看,会发现有bindevetclibprocsyssysrootinit等文件(包含目录)。

    initrd中的内容释放到rootfs(根文件系统)中后,Kernel会执行其中的init文件。

    这个时候内核的控制权移交给init文件处理。

    驱动加载后,会创建一个根设备,然后将根文件系统以只读的方式挂载。

    这步结束后释放未使用内存并执行switch root,转换到真正的根上面去,同时运行/sbin/init程序,开启系统的1号进程,此后系统启动的控制权移交给 init 进程。

    Init初始化阶段

    在核心加载完成之后,系统就准备好了,等待程序的执行。整个linux系统中,第一个执行的程序就是“/sbin/init”。

    具体步骤如下:

    执行系统初始化脚本(/etc/rc.d/rc.sysinit),对系统进行基本的配置,以读写方式挂载根文件系统及其它文件系统,到此系统基本算运行起来了;通过读取配置文件/etc/inittab确定启动后进入的运行级别,在选定运行级别后进入相应的“/etc/rc.d/rcX.d”目录中运行相应的服务内容,该目录下的内容全部都是以S或K开头的链接文件,这些链接文件都链接到“/etc/rc.d/init.d”目录下的各种shell脚本,通过执行这些shell脚本,完成了系统所有的启动任务,linux会启动终端或X-Window来等待用户登录。

    Linux系统启动流程图及其相关文件

    系统执行流程图

    展开全文
  • 前言时光匆碌,不知不觉都大三了,在众多的专业课的学习中也算是找到了一些乐趣,纸上得来终觉浅,所以决定完整的回顾一下整个操作系统的知识,为了理论与实践相结合,以学校实验室的EOS操作系统为例进行实践操作,...

    前言

    时光匆碌,不知不觉都大三了,在众多的专业课的学习中也算是找到了一些乐趣,纸上得来终觉浅,所以决定完整的回顾一下整个操作系统的知识,为了理论与实践相结合,以学校实验室的EOS操作系统为例进行实践操作,作为一个刚刚开始学习操作系统的新手,如果有说的不对的地方还请多多指教。

    EOS 是一个可以在 Intel X86 平台上运行的、面向教学的开源操作系统。为了让 EOS 适合于教学,EOS 被设计的十分小巧,并且尽量保持架构简单。但是,EOS 仍然涵盖了系统引导、进程管理、内存管理、IO 管理、文件系统等重要的操作系统概念。

    系统启动

    我们都知道程序的执行是必须要进去内存之后进行执行,操作系统也可以看做一个程序的运行,如果从开机加载到内存中执行的过程就是系统的启动。
    我们先宏观上看一下整个从CPU加电到操作系统启动的过程:

    1. BIOS 程序首先将存储设备的引导记录(Boot Record)载入内存,并执行引导记录中的引导程序(Boot);
    2. 引导程序会将存储设备中的操作系统内核载入内存,并进入内核的入口点开始执行
    3. 后操作系统内核完成系统的初始化,并允许用户与操作系统进行交互

    这里写图片描述

    1、BIOS程序执行过程

    BIOS(Basic Input/Output System)是基本输入输出系统的简称。BIOS 能为电脑提供最低级、最直 接的硬件控制与支持,是联系最底层的硬件系统和软件系统的桥梁。为了在关机后使 BIOS 不会丢失,早 期的 BIOS 存储在 ROM 中,并且其大小不会超过 64KB;而目前的 BIOS 大多有 1MB 到 2MB,所以会被存储在 闪存(Flash Memory)中。

    BIOS主要的作用:

    • CPU 加电后会首先执行 BIOS 程序,其中 POST(Power-On Self-Test)加电自检程序是执行的第 一个例行程序,主要是对 CPU、内存等硬件设备进行检测和初始化。
    • BIOS 中断调用即 BIOS 中断服务程序,是计算机系统软、硬件之间的一个可编程接口。开机时,BIOS 会通知 CPU 各种硬件设备的中断号,并提供中断服务程序。软件可以通过调用 BIOS 中断对软盘驱动器、键盘及显示器等外围设备进行管理。
    • BIOS 会根据在 CMOS 中保存的配置信息来判断使用哪种设备启动操作系统,并将 CPU 移交给操作系统使用。

    执行过程:

    1. 在CPU加电之后,会把CPU所有寄存器的值设为默认值,除了CS寄存器的值改为0xFFFF,其他寄存器的值都为0,这样,根据CS 和 IP的值就可以找到指令的物理地址0xFFFF:0x0000,也就是0xFFFF0。
    2. 这时CPU就开始执行在这个位置开始执行,这里存放的一条无条件跳转指令JMP,跳转到BIOS的真正启动代码处。
    3. BIOS首先先进行POST(Power-On Self Test,加电后自检)POST的主要检测系统中一些关键设备是否存在和能否正常工作,例如内存和显卡等设备;如果硬件出现问题,主板会发出不同含义的蜂鸣,启动中止。如果没有问题,屏幕就会显示出CPU、内存、硬盘等信息。
    4. BIOS 程序在执 行一些必要的开机自检和初始化后,会将自己复制到从 0xA0000 开始的物理内存中并继续执行
    5. 然后,BIOS 开始搜寻可引导的存储设备(即根据用户指定的引导顺序从软盘、硬盘或是可移动设备)。如果找到,则将存储设备中的引导扇区读入物理内存 0x7C00 处,并跳转到 0x7C00 继续执行,从而将 CPU 交给引导扇区中的 Boot 程序。

    以 EOS 操作系统为例,开机时,如果在软盘驱动器中插有一张 EOS 操作系统软盘,则软盘的引导扇区 (大小为 512 字节)就会被 BIOS 程序加载到物理内存的 0x7C00 处。此时的物理内存如图 3-2 所示。其中, 常规内存(640K)与上位内存(384K)组成了在实模式下 CPU 能够访问的 1M 地址空间。并且此时只有两 个区域的空白物理内存可供正在运行的 Boot 程序使用,即“用户可用(1)”和“用户可用(2)”。
    这里写图片描述

    2、Boot 程序的执行过程

    总结来说,由于Boot程序大小的限制(512KB),所以Boot程序的功能就是为了加载 Loader程序。

    前面的CPU上电及BIOS的工作都不是操作系统能控制的,而从引导扇区开始,就完完全全可由操作系统来控制了,因此,编写引导扇区也是编写操作系统 必要的工作之一。从BIOS跳入引导扇区后,计算机系统引导工作就算完成,怎样把操作系统内核读进内存,然后再安排一条跳转指令跳到内核处执行就是操作系 统开发人员的工作了。

    在 Boot 程序执行的过程中,CPU 始终处于实模式状态。Boot 程序利用 BIOS 提供的 int 0x13 中断服 务程序读取软盘 FAT12 文件系统的根目录,在根目录中搜寻 loader.bin 文件。如果 Boot 程序找到了 loader.bin 文件,会继续利用 int 0x13 功能将整个 loader.bin 文件读入从地址 0x1000 起始的物理内存, 最后跳转到 0x1000 处开始执行 Loader 程序,Boot 程序的使命到此结束。

    EOS中Boot程序源码:

    ;***
    ;
    ; Copyright (c) 2008 北京英真时代科技有限公司。保留所有权利。
    ;
    ; 只有您接受 EOS 核心源代码协议(参见 License.txt)中的条款才能使用这些代码。
    ; 如果您不接受,不能使用这些代码。
    ;
    ; 文件名: boot.asm
    ;
    ; 描述: 引导扇区。
    ;
    ; 
    ;
    ;*******************************************************************************/
    
    ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    ;                               boot.asm
    ;
    ;     PC 机加电后,CPU 进入实模式,分段管理内存,最多访问 1M 地址空间(没
    ; 有打开 A20 的情况下)。CPU 首先执行 BIOS 程序,在 BIOS 完成设备检测等工
    ; 作后,如果 BIOS 被设置为从软盘启动,则 BIOS 会将软盘的引导扇区(512 字节)
    ; 加载到物理地址 0x7C00 - 0x7DFF 处,然后将 CPU 的 CS 寄存器设置为 0x0000,
    ; 将 IP 寄存器设置为 0x7C00,接下来 CPU 就开始执行引导扇区中的程序。
    ;     由于段界限为 64K,所以在不修改段寄存器的情况下只能访问 0x0000 到 0xFFFF
    ; 的地址空间,软盘引导扇区就被加载到了此范围内,所以在软盘引导扇区程序中一般
    ; 不需要修改段寄存器。
    ;     此时的物理内存应该是下面的样子:
    ;
    ;                 +-------------------------------------+----------------------
    ;          0x0000 |                                     |
    ;                 |   BIOS 中断向量表 (1K)              |
    ;                 |   BIOS Interrupt Vector Table       |
    ;                 |                                     |
    ;                 +-------------------------------------+
    ;          0x0400 |   BIOS 数据区 (512 Bytes)           |
    ;                 |   BIOS Data Area                    |
    ;                 +-------------------------------------+
    ;          0x0600 |                                     |
    ;                 |                                     |
    ;                 |             用户可用(1)             |   常规内存 (640K)
    ;                 |                                     |  Conventional Memory
    ;                 |                                     |
    ;                 +-------------------------------------+
    ;          0x7C00 |   软盘引导扇区 (512 Bytes)          |
    ;                 |   Floppy Boot Sector                |
    ;                 +-------------------------------------+
    ;          0x7E00 |                                     |
    ;                 |                                     |
    ;                 |             用户可用(2)             |
    ;                 |                                     |
    ;                 |                                     |
    ;                 +-------------------------------------+----------------------
    ;         0xA0000 |                                     |
    ;                 |                                     |
    ;                 |   系统占用 (384K)                   |   上位内存 (384K)
    ;                 |                                     |   Upper Memory
    ;                 |                                     |
    ;                 +-------------------------------------+----------------------
    ;        0x100000 |                                     |
    ;                 |                                     |   扩展内存(只有进入保护模式才能访问)
    ;                 |               不可用                |  Extended Memory
    ;                 Z                                     Z
    ;                 |                                     |
    ;    物理内存结束 |                                     |
    ;                 +-------------------------------------+----------------------
    ;
    ;     EOS 的软盘引导扇区程序选择将 Loader.bin 从第一个用户可用区域的 0x1000 处开始
    ; 加载,即从 0x1000 到 0x7BFF,所以 Loader 最大只能为 0x7C00 - 0x1000 = 0x6C00
    ; 个字节。如果在保护模式中按照 4K 大小进行分页,则 Loader 就在一个页面的开始处。
    ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    
        org 0x7C00
        jmp short Start
        nop                 ; 这个 nop 不可少
    
    ; ----------------------------------------------------------------------
    ; FAT12 引导扇区头
    Oem                     db 'Engintim'   ; OEM String,必须 8 个字节
    BytesPerSector          dw 512          ; 每扇区字节数                    ----+
    SectorsPerCluster       db 1            ; 每簇多少扇区                        |
    ReservedSectors         dw 1            ; Boot 记录占用多少扇区             |
    Fats                    db 2            ; FAT 表数                            |
    RootEntries             dw 224          ; 根目录文件数最大值             |
    Sectors                 dw 2880         ; 扇区总数                          \\ BPB
    Media                   db 0xF0         ; 介质描述                          // BIOS Parameter Block
    SectorsPerFat           dw 9            ; 每 FAT 扇区数                     |
    SectorsPerTrack         dw 18           ; 每磁道扇区数                        |
    Heads                   dw 2            ; 磁头数                           |
    HiddenSectors           dd 0            ; 隐藏扇区数                     |
    LargeSectors            dd 0            ; 扇区总数,Sectors 为 0 时使用  ----+
    DriveNumber             db 0            ; 驱动器号
    Reserved                db 0            ; 保留未用
    Signature               db 0x29         ; 引导标记 (0x29)
    Id                      dd 0            ; 卷序列号
    VolumeLabel             db 'EOS        '; 卷标,必须 11 个字节
    SystemId                db 'FAT12   '   ; 文件系统类型,必须 8 个字节
    ;------------------------------------------------------------------------
    
    ; FAT12 文件系统相关的一些变量
    FirstSectorOfRootDir    dw 0            ; 根目录的起始扇区号
    RootDirectorySectors    dw 0            ; 根目录占用的扇区数量
    FirstSectorOfFileArea   dw 0            ; 数据区的起始扇区号
    BufferOfFat             dw 0            ; FAT 表缓冲区地址
    BufferOfRootDir         dw 0            ; 根目录缓冲区地址
    
    LOADER_ORG              equ 0x1000              ; Loader.bin 的起始地址
    MAX_FILE_SIZE           equ 0x6C00              ; Loader.bin 只占用 0x1000 到 0x7C00 的空间
    wFilePos                dw  LOADER_ORG          ; 用于加载 Loader.bin 的游标
    LoaderFileName          db  "LOADER  BIN"       ; Loader.bin 的文件名
    strError:               db  "File Loader.bin not found!"
    
    Start:
        ; 初始化 CPU 的段寄存器为 CS 的值(0),堆栈从 64K 向下增长
        mov ax, cs
        mov ds, ax
        mov es, ax
        mov ss, ax
        xor sp, sp
        mov bp, sp
    
        ; 初始化屏幕
        mov ax, 0x0600      ; AH = 0x06,  AL = 0x00
        mov bx, 0x0700      ; 黑底白字(BH = 0x07)
        xor cx, cx          ; 左上角: (列号  0, 行号  0)
        mov dx, 0x184F      ; 右下角: (列号 79, 行号 24)
        int 0x10
    
        ; 软驱复位
        xor ah, ah
        xor dl, dl
        int 0x13
    
        ;
        ; 计算根目录的起始扇区号
        ; FirstSectorOfRootDir = ReservedSectors + SectorsPerFat * Fats
        ;
        mov ax, word [SectorsPerFat]
        movzx bx, byte [Fats]
        mul bx
        add ax, word [ReservedSectors]
        mov word [FirstSectorOfRootDir], ax
    
        ;
        ; 计算根目录占用的扇区数量
        ; RootDirectorySectors = RootEntries * 32 / BytesPerSector
        ;
        mov ax, word [RootEntries]
        shl ax, 5
        mov bx, word [BytesPerSector]
        div bx
        mov word [RootDirectorySectors], ax
    
        ;
        ; 计算数据区域的起始扇区号
        ; FirstSectorOfFileArea = FirstSectorOfRootDir + RootDirectorySectors
        ;
        add ax, word [FirstSectorOfRootDir]
        mov word [FirstSectorOfFileArea], ax
    
        ;
        ; 计算 FAT 缓冲区地址(紧接在引导扇区后)
        ; BufferOfFat = 0x7C00 + BytesPerSector * ReservedSectors
        ;
        mov ax, word [BytesPerSector]
        mul word [ReservedSectors]
        add ax, 0x7C00
        mov word [BufferOfFat], ax
    
        ;
        ; 计算根目录缓冲区地址(紧接在 FAT 缓冲区后)
        ; BufferOfRootDir = BufferOfFat + BytesPerSector * SectorsPerFat
        ;
        mov ax, word [BytesPerSector]
        mul word [SectorsPerFat]
        add ax, word [BufferOfFat]
        mov word [BufferOfRootDir], ax
    
        ; 将 FAT1 读入 FAT 缓冲区
        mov ax, word [ReservedSectors]      ; 
        mov cx, word [SectorsPerFat]        ; 一个 FAT 表的扇区数量
        mov bx, word [BufferOfFat]          ; es:bx 指向 FAT 表缓冲区
        call ReadSector
    
        ; 将根目录读入缓冲区
        mov ax, word[FirstSectorOfRootDir]
        mov cx, word[RootDirectorySectors]
        mov bx, word[BufferOfRootDir]
        call ReadSector
    
        ; 在根目录中查找 Loader.bin 文件
    FindFile:
        mov bx, word [BufferOfRootDir]      ; bx 指向第一个根目录项
        mov dx, word [RootEntries]          ; 根目录项总数
        cld
    
    CompareNextDirEntry:
        mov si, LoaderFileName              ; si -> "LOADER  BIN"
        mov di, bx                          ; di -> 目录项中文件名字符串
        mov cx, 11                          ; 文件名字符串的长度
        repe cmpsb                          ; 字符串比较
        cmp cx, 0
        je  CheckFileSize                   ; 如果比较了 11 个字符都相等, 表示找到文件
    
        ; 文件名不一致,继续比较下一个目录项
        add bx, 0x20                        ; bx 指向下一个目录项
        dec dx                              ; 减小剩余目录项
        jnz CompareNextDirEntry
    
        ; 查找完所有目录项仍没有找到文件,提示出错
        jmp Error
    
        ; 找到文件后,检查文件的大小
    CheckFileSize:
        mov eax, dword [bx + 0x1C]          ; 得到文件的大小
        test eax, eax
        jz Error
        cmp eax, MAX_FILE_SIZE
        ja Error
    
        ; 开始加载文件
        mov ax, word [bx + 0x1A]            ; 初始化 ax 为文件的第一个簇号
    ReadNextCluster:
        push ax                             ; 保存要读取的簇号
    
        ;
        ; 计算 ax 号簇对应的扇区号,扇区号 = 数据区起始扇区号 + (簇号 - 2) * 每簇扇区数
        ;
        sub ax, 2
        movzx cx, byte [SectorsPerCluster]
        mul cx
        add ax, word [FirstSectorOfFileArea]
    
        mov bx, word [wFilePos];            ; 文件缓冲区地址
    
        call ReadSector                     ; 读一个簇
    
        ;
        ; 文件位置向后移动一个簇的大小
        ; wFilePos = wFilePos + BytesPerSector * SectorsPerCluster
        ;
        mov ax, word [BytesPerSector]
        movzx bx, byte [SectorsPerCluster]
        mul bx
        add ax, word [wFilePos];
        mov word [wFilePos], ax     
    
        ; 查找 FAT 表,获得下一个要读取的簇
        pop ax                              ; 刚读取的簇号
        mov bx, 3
        mul bx
        mov bx, 2
        div bx
        mov bx, word [BufferOfFat]
        add bx, ax
        mov ax, word [bx]
        test dx, dx
        jz EvenClusterNo
        shr ax, 4
        jmp CheckEOC
    EvenClusterNo:
        and ax, 0x0FFF
    
        ; 根据簇号判断文件是否结束,如没结束则继续读取
    CheckEOC:
        cmp ax, 0x0FF7
        jb  ReadNextCluster
    
        ; 文件读取完毕,关闭软驱马达
        mov dx, 0x03F2
        xor al, al
        out dx, al
    
        ; Loader.bin 加载完毕,跳转到 Loader.bin 执行
        jmp 0:LOADER_ORG
    
        ; 出错处理:在屏幕左上角显示错误信息字符串,并且死循环
    Error:  
        mov bp, strError
        mov ax, 0x1301              ; AH = 0x13,  AL = 0x01
        mov bx, 0x0007              ; 页号为 0 (BH = 0x00),黑底白字 (BL = 0x07)
        mov cx, 26                  ; 字符串长度
        xor dx, dx
        int 0x10
        jmp $
    
    ;----------------------------------------------------------------------------
    ; 函数名: ReadSector
    ; 作  用: 从第 ax 个 Sector 开始, 将 cl 个 Sector 读入 es:bx 中
    ;----------------------------------------------------------------------------
    ReadSector:
        push bp
        mov bp, sp
        push cx                     ; 保存 cl
        push bx                     ; 保存 bx
    
        ;
        ; 计算 柱面号、起始扇区 和 磁头号
        ; 设扇区号为 x
        ;                           ┌ 柱面号 = y >> 1
        ;       x           ┌ 商 y ┤
        ; -------------- => ┤      └ 磁头号 = y & 1
        ;  每磁道扇区数     │
        ;                   └ 余 z => 起始扇区号 = z + 1
        ;
        mov bl, [SectorsPerTrack]   ; bl: 除数
        div bl                      ; y 在 al 中, z 在 ah 中
        inc ah                      ; z ++
        mov cl, ah                  ; cl <- 起始扇区号
        mov dh, al                  ; dh <- y
        shr al, 1                   ; y >> 1 (其实是 y / Heads, 这里 Heads = 2)
        mov ch, al                  ; ch <- 柱面号
        and dh, 1                   ; dh & 1 = 磁头号
        mov dl, [DriveNumber]       ; 驱动器号 (0 表示 A 盘)
        pop bx                      ; 恢复 bx
    
    .GoOnReading:
        mov ah, 2                   ; 读
        mov al, byte [bp-2]         ; 读 al 个扇区
        int 0x13
        jc  .GoOnReading            ; 如果读取错误 CF 会被置为 1, 这时就不停地读, 直到正确为止
    
        ; 恢复堆栈并返回
        pop cx
        pop bp
        ret
    
        ;
        ; 引导扇区代码结束,填充剩下的空间,使生成的二进制代码恰好为 512 字节
        ;
        times   510-($-$$)   db  0
        dw  0xaa55                  ; 引导扇区激活标志
    

    3、Loader 程序的执行过程

    Loader 程序的任务和 Boot 程序很相似,同样是将其它的程序加载到物理内存中,这次加载的是操作系统(EOS)内核。除此之外,Loader 程序还负责检测内存大小,为内核准备保护模式执行环境等工作。
    简单来说,Loader程序就是从软盘的根目录将内核文件kernel.dll载入物理内存0x10000,然后通过开启分页机制,映射到虚拟地址0x80000000处,然后Loader程序跳转到kernel.dll的入口点继续执行,到此,控制权交给了内核。

    Loader程序的汇编实现相当复杂,就不在此贴出来了

    4、内核初始化过程

    总的来说,内核初始化的主要是初始化处理器和中断、各个管理模块、最后创建主进程。之后启动控制台程序,这样就可以交互,进行应用程序的执行了

    EOS中内核的入口程序:

    /***
    
    Copyright (c) 2008 北京英真时代科技有限公司。保留所有权利。
    
    只有您接受 EOS 核心源代码协议(参见 License.txt)中的条款才能使用这些代码。
    如果您不接受,不能使用这些代码。
    
    文件名: start.c
    
    描述: EOS 内核的入口函数。
    
    
    
    *******************************************************************************/
    
    #include "ki.h"
    #include "mm.h"
    #include "ob.h"
    #include "ps.h"
    #include "io.h"
    #include "kdb.h"
    
    VOID
    KiSystemStartup(
        PVOID LoaderBlock
        )
    /*++
    
    功能描述:
        系统的入口点,Kernel.dll被Loader加载到内存后从这里开始执行。
    
    参数:
        LoaderBlock - Loader传递的加载参数块结构体指针,内存管理器要使用。
    
    返回值:
        无(这个函数永远不会返回)。
    
    注意:
        KiSystemStartup在Loader构造的ISR栈中执行,不存在当前线程,所以不能调用任何可
        能导致阻塞的函数,只能对各个模块进行简单的初始化。
    
    --*/
    {
        //
        // 初始化处理器和中断。
        //
        KiInitializeProcessor();
        KiInitializeInterrupt();
    
        //
        // 初始化内核调试桩。
        // 注意:在调试桩初始化完成之前,设置断点是不会命中的。
        //
    #ifdef _DEBUG
        KdbInitializeSystem();
    #endif
    
        //
        // 初始化可编程中断控制器和可编程定时计数器。
        //
        KiInitializePic();
        KiInitializePit();
    
        //
        // 对各个管理模块执行第一步初始化,顺序不能乱。
        //
        MmInitializeSystem1(LoaderBlock);
        ObInitializeSystem1();
        PsInitializeSystem1();
        IoInitializeSystem1();
    
        //
        // 创建系统启动进程。
        //
        PsCreateSystemProcess(KiSystemProcessRoutine);
    
        //
        // 执行到这里时,所有函数仍然在使用由 Loader 初始化的堆栈,所有系统线程
        // 都已处于就绪状态。执行线程调度后,系统线程开始使用各自的线程堆栈运行。
        //
        KeThreadSchedule();
    
        //
        // 本函数永远不会返回。
        //
        ASSERT(FALSE);
    }
    

    参考资料

    1.EOS 操作系统实验教程 海西慧学 编著
    2.计算机的启动过程(详细)
    3. 从开机到进入操作系统的引导过程详解

    展开全文
  • 操作系统启动过程

    2018-05-06 10:27:18
    转自:...那到底是什么让操作系统加载到我们的cpu上面,供我们的使用的呢??电脑执行的第一条指令是从哪里来的呢?? 答案就是,电脑cpu分为两部分,一部分为RAM 随机访问存储,还有一个...

    转自:https://blog.csdn.net/MosBest/article/details/52107574

    粗略版

    我们知道,操作系统是放在磁盘上的,而电脑的指令只能再cpu里执行,cpu在掉电的时候所有的内容都要清空。那到底是什么让操作系统加载到我们的cpu上面,供我们的使用的呢??电脑执行的第一条指令是从哪里来的呢?? 
    答案就是,电脑cpu分为两部分,一部分为RAM 随机访问存储,还有一个ROM只读存储。 
    电脑在上电之后,cpu的ROM 只读存储 里头还会有一些我们原来写入的一些内容。我们的系统初始化代码就从那里开始执行。大小大约1M左右,这就是我们熟知的BIOS固件。 
    这里写图片描述 
    ROM就是上图从下到上的1M的内容,里面就含有BIOS。电脑一上电,cpu就开始执行他。

    我们还要知道,电脑一上电怎么就能够找到BIOS的起始位置呢?? 
    我们要求,在系统CPU完成初始化之后,它处于实模式下。 在实模式下,它的地址计算把段寄存器左移四位,然后加上它的当前指令指针,这两个加在一起作为我们当前访问第一条指定位置。即 
    这里写图片描述 
    PC就是第一条指令的起始位置。

    还有一条限制是说,在加电的时候 ,它处于实模式 
    这个时候地址总线,并不是像我们现在用到通常系统是32位,它只有20位的地址可用,那在这20位地址里头,我们用的区域就是2的二十次方,这个时候就只有1M。这就解释了为什么放的区域就只能放在最底下1M里头一小块。

    这块代码它为了从磁盘上读数据,那这个时候必须提供相应的服务,如果没有这些服务,你是没有办法访问到磁盘设备的。 
    为了做到这件事情,在BIOS里头 它需要提供这样一些功能,分别为: 
    1. 基本的输入输出 
    2. 然后系统的配置信息 
    3. 开机自检程序 
    4. 系统自启动程序 
    * 基本输入 输出 
    在屏幕上显示基本的信息,从磁盘上读写扇区,知道我的内存有多大,从键盘上读用户的输入。当然在这里BIOS只能提供最简单,最基本的输入 输出功能。并且它的使用也受到很大的限制,比如说在我们的英特尔的CPU上,它受到一条限制,就是你只能是在实模式下工作。那如果说我们的操作系统是工作在保护模式下,那这些就都不可以用了。 
    * 然后系统的配置 
    我们都知道系统在刚开始的时候,你需要有配置,到底是从硬盘启动 ,从网络启动,还是说从光盘启动。 
    这些启动是在你加电的时候,由你的BIOS的设置来完成。依据这些设置,系统执行它的启动程序。就是把硬盘里的加载程序和操作系统内容先后加载到cpu当中当中来。

    具体的过程 我们可以这样来看 
    在BIOS初始化完成之后,BIOS它就会从磁盘上把引导散区的程序( 
    这个引导散区是只有长度512字节) 读取到cpu的指定位置0x7C00。然后cpu就跳转到该固定位置,把控制权转到从磁盘上读进来的这个程序,我们称他为 “加载程序”。加载程序里头我们又可以做进一步的事情。(更长的它没有这个能力。在BIOS程序,它不允许你能读更多内容)。

    这加载程序能干什么呢??? 
    它能将操作系统的代码读到内存里头来,并且能把控制权交给操作系统,来继续执行操作系统功能。 
    这里写图片描述 
    如上图所示,把加载程序放在了cpu地址为0X7C00上面了(位于BIOS下面,所以不能大)。操作系统放在了BIOS的上面。

    这个时候有个问题 ,你既然能从磁盘上读数据,那为啥我不直接从BIOS里头直接把操作系统的内核映像读进来呢??? 
    实际上,首先我们磁盘上是有文件系统的,文件系统是多种多样的。我们在机器出厂的时候,不可以说我直接限制死你,你只能用某一种文件系统。为了增加这种灵活性,但是我在BIOS又不可能加上认识所有文件系统代码。 
    那怎么办? 我就在里有一个基本约定 
    我不需要认识格式,我也能从里头读到你的第一块。我只读第一块。 
    读了这块之后 ,这块的加载程序里头,我们会用加载程序来识别你磁盘上文件系统。这时候,我就能够认识磁盘上文件系统,我就可以读到我内核的镜像,并且把它加载到内存当中来。这就是我们这里看到,用加载程序读到操作系统来。有了这个过程之后,我们再把相应的控制权转到读进来的操作系统内核代码上,我们操作系统就可以开始运行的。

    略详细版

    其实在cpu初始化完成后,BIOS并不是直接去读磁盘扇区的加载程序的。 
    比如说我们在最早的时候,电脑磁盘里只有一个分区,cpu和BIOS都初始化完成之后就直接到分区里找文件系统了。但是对于我们现在来说,所有的计算机,或者大多数的计算机里头都不止一个分区,可能会有几个分区。每个分区上会装不同的系统。那这个时候就在前边加上一个主引导记录。 
    这个主引导记录是说,我要从哪个文件系统里去读我的这个加载程序。在主引导记录执行完,然后我就进到当前某一个分区里头,分区里头又有该分区的引导扇区,通过这个活动分区的引导扇区,再来加载我们刚才说到的加载程序。可以参考下面这张图。第一个框是在cpu上面执行的,其他三个是在磁盘上面执行的。 
    这里写图片描述

    那我们具体说起来,有这样几个过程!!!

    1. cpu初始化,找到自己的第一条指令!!! 
      首先我们在前面已经说过,CPU加电完成它的初始化,到一个确定的状态去读第一条指令。我们需要知道CPU初始化之后,它的代码段段寄存器和当前指令指针寄存器这两个的内容,算出来它的第一条指令在内存当中的什么地方。 
      因为它是实模式,所以是CS和IP都是16位的,CS左移四位和IP加在一起算出我的位置。这个时候 我放到内存当中的BIOS的位置,只能是在最底下的一兆,原因在于这时候它是20位的地址。有了这个之后我们就直接进到BIOS里执行。

    2. 进入BIOS,进行BIOS的初始化!!! 
      首先第一个是硬件自检 
      也就是说我们有可能加电起来之后,你的内存出错, 那整个后边就没法做。 
      我们说在计算机系统里头它的加电自检,它上来之后是看最关键的这几个部分是不是在工作。这就相当于在自检的时候关键的内存 显卡这几部分是否存在,如果存在的话 ,它的工作状态是什么样子。 
      然后完成设备每一个这些关键性的接口卡里头它自己的初始化程序。这些初始化程序完成之后,那我就认为关键的设备是可以的了。

      然后是使用系统配置表,找到指定外部设备的系统(比如,U盘,磁盘等) 
      我们说我们现在的系统,很多都是可以即插即用的。如果说我想从一个USB接口的光驱里启动,那你怎么启得来??? 
      这时候, 在这个BIOS里的自检,现在是能够做到系统的自检!!! 我们说在BIOS里有一个系统配置表,这个配置表就是我们这里所说的 ESCD ,就是扩展系统配置数据。那用这个数据 我就能知道,我当前系统里都有些什么样的设备。每次加电之后有可能你会插上新的卡或者说拔掉已有的卡,这个数据会因为这些操作而发生改变。每次加电的时候这个数据都必须审阅,可能会修改一次。做完之后,我就把控制权转到我们从磁盘读到cpu的数据里头。读进去的数据就是我们说的主引导记录。

    3. 主引导记录MBR格式 
      这里写图片描述

      由于有的电脑不止一个分区,所以上面我们说的,读入到cpu的数据,就是我们需要的主引导记录。我们说主引导记录有512字节,但是在这 ,你只能说我可以用到的是446字节。 
      那其他部分是什么??原因是当我的电脑后边有多个分区的时候,要把这些分区的状态也要存到这512字节里头。由上图可以看到,每个分区的信息占用16个字节,所以硬盘分区表里最多只能有4个分区。 
      所以这样的话,你就只有446个字节的内容来执行你的启动代码。而这个启动代码是用来检查我分区表是否正确,然后还要加载并跳转到你的活动分区的引导记录上去。 
      前面的是启动代码446字节,中间的你的硬盘分区表16*4=64字节。最后是一个结束标志,这个结束标是55AA,有了这个之后 ,它才认为这是一个合法的主引导记录。

    4. 分区引导扇区格式 
      这里写图片描述
      那有了以上主引导的操作之后,它就会跳到你活动分区的引导扇区上去。 
      从上图可以看出, 
      先是跳转指令,跳转指令平台相关了, 你的CPU不同,这个地方这条指令肯定也是不一样的。 
      然后是文件卷的信息。 
      再之后是我的启动代码,这个地方的启动代码就需要认识你的格式说,我这个加载程序不是存在在512字节里头的,存在别处的。它在哪?那就靠你这里的代码来约定说我放在哪。而这里的代码实际上是我们存在硬盘上的或者说你的软盘上的,因此我是可以改动的,那改动完了之后,我就可以把我的加载程序放在任意的地方,只要我在这标识出来我上哪去认识它就可以。 
      最后是结束标志,这个结束标志跟刚才那个主引导记录是一样的,也是55AA。有了这个之后 ,它才认为这是一个合法的分区引导。

    5. 加载程序(bootloader) ,开始加载我的操作系统到我的cpu里面的 
      这里写图片描述
      从上面分区的启动代码,就找到了我的加载程序。 
      接下来我们说加载程序的细化 
      我们说加载程序它首先不是直接去加载你的内核,而是去文件系统当中读一个启动配置文件。依据配置文件的配置(参数)去加载内核,依据这个,就选择你启动的模式,比如说我是在正常启动,还是说我是在安全模式启动,还是说我是在一个调试状态下启动我的系统。 
      那这些区别都会读出来之后,它导致我在加载内核的时候的一些内核会不一样,或者说我加载的时候的参数会不一样。


    展开全文
  • 错误,无法正常启动操作系统, 一开始出现图一,重启大法几次之后就变成图二了,现在是由于什么原因造成的还不清楚,我出现这种情况是因为自己笔记本忘记关机直至电量耗尽,再次打开电脑就这样报错了,网上大多数...

    bootsafe64_ev.sys

    错误,无法正常启动操作系统,1737834-20190902093218694-903491377.png
    1737834-20190902093229090-1106320499.png
    一开始出现图一,重启大法几次之后就变成图二了,现在是由于什么原因造成的还不清楚,我出现这种情况是因为自己笔记本忘记关机直至电量耗尽,再次打开电脑就这样报错了,网上大多数建议是因为重新安装操作系统,但我觉得这太绝对了,先不说重装的系统一般不会比原有的系统好,而且各种资料软件(如office)还要重装或者备份,其实只是删除两个文件的事情。

    bootsafe64.sys删除,kavbootc.sys删除

    现在就是解决怎么才能去删除文件。

    1.像微软官网给的提示,开机,再关机,重复几次进入修复模式,这种我没有尝试,不过如果可以进入命令行操作电脑,那就是可以实现文件的操作的。

    2.通过u盘的pe系统来进入开启电脑,再操作c盘执行文件的增删。(这种是较为简单的方法,但我还是遇到了很多问题)

    问题:

    1.戴尔操作系统的BIOS操作界面是不一样的,我也不知道为什么要搞特殊,不过新的东西真的很难搞,因为没资料。

    2.千辛万苦终于进入u盘启动的设置页面,但是进入系统之后却发现c盘被锁住了,BitLocker我真的是谢谢你,平时没怎么在意,真正用到了却是在我自己头上。

    现在主要讲第二个问题,第一个问题暂时放着,因为自己也是百度出来的。

    BitLocker这个是驱动加密的程序,一般的pe系统不会自带这个东西,像大白菜什么的(顺便说一句,个人建议,不要使用大白菜这些软件,虽然推广的很多很多,但是用到了你就知道有多坑了,而且交流群压根不理你)

    解密BitLocker需要特殊的pe操作系统,其他网上说的我也不知道有没有用,我用成功的是USBOS

    http://bbs.wuyou.net/forum.php?mod=viewthread&tid=349965&extra=page%3D1
    搭个链接,资源也有可以私信。

    这个pe系统是我所有测试中用到的最好的,没有之一,不管是界面还是功能,USBOS增强版中就有BitLocker解锁的功能,只要输入密匙就可以解密了。

    https://account.microsoft.com/devices/
    进入这里,用你的微软账户登录他会保存你使用过的电脑,找到是你的那一个,

    1737834-20190902093248888-21664978.png

    1737834-20190902093255506-482795388.png

    点击管理-->管理恢复密钥-->手机验证码或者邮箱验证身份,这里可能会有几个密钥,因为每个驱动盘对应的都是不一样的,怎么找到c盘对应的,这就需要电脑端进入恢复环境,也就是一开始第二张图片的(网上找的,但是一般会有recover environment) 进入之后会要求你输入密钥,而其中就包含着驱动器c盘的信息,选择对应的就可以。

    现在总结一下,需要的:

    1.usbos的u盘启动盘

    2.微软BitLocker的密钥

    转载于:https://www.cnblogs.com/1120lwk/p/11444769.html

    展开全文
  • 安装完windows8 后开始安装sql2012,安装过程中停在“正在启动操作系统功能"NetFx3"”不动了,很是着急,于是上网查了一下资料,原来NetFx3指的是Framework3.5, 于是从微软官方下载了framework 3.5,安装完后,...

    安装完windows8 后开始安装sql2012,安装过程中停在“正在启动操作系统功能"NetFx3"”不动了,很是着急,于是上网查了一下资料,原来NetFx3指的是Framework3.5,

    于是从微软官方下载了framework 3.5,安装完后,继续按照sql2012,顺利通过。

    展开全文
  • 原本的启动是从img启动的,而且这个img是用FAT12文件系统进行格式化的(具体去搜索FAT12文件格式,这里给大家推荐一篇http://www.doc88.com/p-646605198560.html),那么也就是说我们的img文件符合FAT12文件系统的...
  • 错误,无法正常启动操作系统, 一开始出现图一,重启大法几次之后就变成图二了,现在是由于什么原因造成的还不清楚,我出现这种情况是因为自己笔记本忘记关机直至电量耗尽,再次打开电脑就这样报错了,网上大多数...
  • 问题VM中启动操作系统时出现“Failed to launch peer process”的错误,如下图: 解决可能的原因是,内存中已经存在着VM的程序,但不占用CPU资源。这时需要注销或重新启动电脑,刷新内存后再启动VM即可。
  • 如果我们有两个操作系统,那...BIOS在完成启动自检后,然后BIOS就按照系统CMOS设置中保存的启动顺序搜寻软驱、IDE设备和它们的启动顺序,读入操作系统引导记录,最后将系统控制权交给引导记录,并最终完全过渡到操作系
  •  批处理(BatchProcessing)操作系统的工作方式是:用户将作业交给系统操作员,系统操作员将许多用户的作业组成一批作业,之后输入到计算机中,在系统中形成一个自动转接的连续的作业流,然后启动操作系统,系统自动...
  • 从0开始全新重装mac os操作系统 重装mac系统有两种方法,一种是网络安装,一种是自己下载mac os系统安装包,制作启动系统安装盘,通过U盘(或者移动硬盘、光盘)安装。这里这两种方法进行介绍,希望给有需要的朋友...
  • BIOS控制着什么 熟悉计算机的朋友都知道BIOS这个概念,我们也会经常听到老鸟在解决系统故障时候重复的 那些话语:“先清除一下CMOS”或者“进入BIOS默认设置”等等。在普通人眼里,BIOS似乎 就是主机板上那块四四...
  • 当删除一个操作系统时,有的时候引导区不能自动修正,下面时我遇到的一个情况,然后处理的。1、在命令行中输入:c:boot.ini。或者在c盘下寻找隐藏的系统文件boot.ini,右键“属性”,去掉只读的选项。用记事本打开该...
  • 整个启动和加载过程可分为若干步骤,或者称为若干个状态,或者快照,下面的每一段都是描述一个快照。(类似自动状态机)   1、电源稳定(POWER GOOD)   按下启动键后,电源首先启动。为了保证安全使用,电源的...
  • 操作系统是如何启动的(这样的学习太抽象,不太好理解和记忆) 先解释几个基本概念: 操作系统一开始是放在硬盘disk上的 BIOS:一个应用程序,基本IO处理系统,使计算机在开机时检测各种外设 Bootloader:一个...
  • 操作系统的两种模式 1.实模式(实地址模式) 计算机刚加电时处于实模式下 程序按照8086寻址方式访问0h-FFFFFh(1MB)空间 寻址方式:物理地址(20位)=短地址:偏移地址 CPU单任务运行 2.保护模式 计算机启动成功...
  • Linux操作系统之一:简述Linux系统开机引导和启动过程操作系统启动分为两个阶段:引导boot启动startup引导阶段开始于打开电源开关,结束于内核初始化完成和 systemd 进程成功运行。启动阶段接管了剩余工作,直到...
  • 最近试读了《30天自制操作系统》的前两章,感觉很有意思。 但是发现里面写的系统都是用软盘启动的,现在在大多数电脑上已经看不见软驱了,所以如果想运行书中的操作系统只能通过qemu(随书光盘中已经附带)模拟运行...
  • PXE(Pre-boot Execution Environment,预启动执行环境)是由Intel公司开发的最新技术,工作于Client/Server的网络模式,支持工作站通过网络从远端服务器下载映像,并由此支持通过网络启动操作系统,在启动过程中,...
  • 重装电脑操作系统 要装操作系统首先得有系统镜像,在此只介绍通过U盘重装 1、下载需要的系统ios镜像 首先可以选择下载自己需要的Windows镜像,可以在百度上搜索,以下是我通过网盘分享的几个镜像: 网盘...
1 2 3 4 5 ... 20
收藏数 1,608,496
精华内容 643,398