Linux
This presentation is the property of its rightful owner.
Sponsored Links
1 / 45

Linux 内核源代码导读 PowerPoint PPT Presentation


  • 132 Views
  • Uploaded on
  • Presentation posted in: General

Linux 内核源代码导读. 中国科学技术大学计算机系 陈香兰( 0551 - 3606864 ) [email protected] Spring 2009. 回顾编译得到的 bzImage 的结构 Setup.bin+vmlinux.bin (具有自解压能力). head_32.o+misc.o+piggy.o. vmlinux. Head-y + init-y + main. 基于 I386 的 Linux 的启动. 计算机是如何启动的. BIOS 软盘启动 硬盘启动 Grub Lilo 启动协议. 特殊的几个地址

Download Presentation

Linux 内核源代码导读

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Linux内核源代码导读

中国科学技术大学计算机系

陈香兰(0551-3606864)

[email protected]

Spring 2009


  • 回顾编译得到的bzImage的结构

  • Setup.bin+vmlinux.bin(具有自解压能力)

head_32.o+misc.o+piggy.o

vmlinux

Head-y + init-y + main


基于I386的Linux的启动


计算机是如何启动的

  • BIOS

  • 软盘启动

  • 硬盘启动

  • Grub

  • Lilo

  • 启动协议


  • 特殊的几个地址

  • BIOS:第一个扇区0x07c0

  • 第一个扇区的内容是什么?

    • 观察setup.ld

      • 了解第一个扇区的内容


关键:

阅读: documentation/i386/boot.txt

  • 实模式

  • 保护模式

  • 分页模式

    • 页表

  • GDT表

  • IDT表


I386内核从实模式开始运行

首先看一下什么是实模式

  • 实模式是为了兼容早期的CPU而设置的

  • i386系统总是始于实模式

  • 实模式下

    • 地址总线:20位

    • 内存范围:0~1MB

    • 逻辑地址 = 段地址 + 段内偏移

      • 段地址 = 段寄存器中的值*16 (或左移4位)

      • 段寄存器长度:16bit

    • 段寄存器有:

      • cs/ds/es/fs/gs


  • 保护模式下,

    • 地址总线32位,访存范围为4GB

    • 原来的段寄存器现在被称作段选择子,与GDT表配合使用

      • GDT表由gdtr指示其位置和长度

      • 使用特殊的指令进行操作:sgdt/lgdt


Interrupt Descriptor

Table

descriptor

Global Descriptor

Table

descriptor

descriptor

descriptor

descriptor

descriptor

descriptor

descriptor

descriptor

descriptor

descriptor

descriptor

descriptor

descriptor

descriptor

descriptor

GDTR

descriptor

descriptor

descriptor

descriptor

IDTR

图示


  • 一般装载gdt和idt之后,要重新装载段寄存器

    • cs、ds、es、fs、gs

    • cs通常通过一条长跳转指令装载

    • 其他数据段寄存器直接设置


控制寄存器(Control Registers)

  • CR0

  • CR1

  • CR2

  • CR3

  • CR4(扩展相关,忽略)

  • 与内存相关


CR0

  • CR0, MSW register (Machine Status Word, 32-bit version)

    • 包含系统控制位,用于控制操作模式和状态

  • Instruction: lmsw

    • LINUX’ setup.S:

      • movw $1, %ax

      • lmsw %ax

      • jmp flush_instr // why?

      • flush_instr:

    • To turn on the PE-bit (enables protected-mode),

  • PE-bit (Protection Enabled)

    • 0 CPU is in real-mode, 1 CPU is in protected-mode


CR1、CR2、CR3

  • CR1:保留

  • CR2:在缺页异常的时候,记录缺页地址

  • CR3:记录页目录所在的物理地址和两个标记(PCD & PWT)


阅读documentation/i386/boot.txt

  • 对于i386平台,由于一些历史的原因,因此Linux的启动比较复杂

  • 这个文档包含如下内容

    1、Linux/i386的启动协议(10个+)

    2、内存布局图(大内核,小内核)

    3、实模式下的内核头结构(即setup header)以及各参数的解释

    4、内核的命令行(command line)


5、实模式代码的内存布局

6、启动配置示例

7、装载Linux的剩余部分

8、特殊的命令行参数

9、运行内核

10、高级启动回调函数

  • 关于其中的一些内容,我们将在合适的时候说明


加载I386内核的内存布局图

  • zImage/Image的内核加载器所使用的经典的内存布局(1M=0x100000)为


Header.S分析

  • 前512个字节的内容


关于msg_loop输出的字符串

??不支持软盘启动???


Header.S分析

  • 关于512字节的最后(setup header)

在setup.ld中

在Head.S中


Header.S分析

  • 第二个扇区开始

  • 接下来仍然是setup header参数部分,直到start_of_setup


  • start_of_setup

    • 设置堆栈

    • 检查setup中的标签

    • 清除BSS段

    • 调用C入口main

_start(512处)

start_of_setup

main


Main.c分析

main

重点:

go_to_protected_mode

=?


关于go_to_protected_mode

  • 关键

move_kernel_around

setup_idt

重点:

setup_gdt

protected_mode_jump:参见pmjump.S


关于protected_mode_jump

  • 关键

    • 进入保护模式

      • 通过设置cr0

    • 进入32位代码

      • 通过一条手工设置的代码

    • 最后进入setup header中指定的code32_start


关于boot_params.hdr.code32_start

  • 对boot_params.hdr的赋值之处:copy_boot_params

  • Hdr的定义之处

在Head.S中


  • code32_start在setup header的第二部分

  • 此处对应于压缩映像的head_32.S


解压缩头中的head_32.S

  • 32位代码

  • 关键1:调用decompress_kernel

  • 关键2:跳转到vmlinux的头head_32.S

  • 阅读此目录下的vmlinux_32.lds

    • 了解入口处的代码


关于解压缩head_32.S中的relocated相关

  • 即“.text”部分

    • Clear BSS

    • Setup the stack for the decompressor

    • Do the decompression, and jump to the new kernel..


Vmlinux中的head

  • 观察vmlinux.lds

    • 观察“.text.head”、“.text”、“.data”等

  • .text.head

    • Set segments to known values.

    • Clear BSS first so that there are no surprises...

    • Copy bootup parameters out of the way.

    • Initialize page tables.

    • Enable paging

    • Set up the stack pointer

    • Initialize eflags.

    • call setup_idt

    • check if it is 486 or 386.

    • call check_x87

    • 装载GDT、IDT,进入3G地址空间

    • jmp i386_start_kernel

startup_32

最后

i386_start_kernel

重点

start_kernel

重点


关于页表的初始化

  • 观察default_entry后的代码,忽略PAE

    • 页目录:swapper_pg_dir:参见head_32.S

      • 第一个页表:pg0:参见vmlinux_32.lds


swapper_pg_dir


pg0

pg0

高地址

内核BSS段

swapper_pg_dir

内核数据段

内核代码段

低地址


初始化页目录和页表

物理地址

空间低端4M

对应线性地址3GB

1024项

对应线性地址0

swapper_pg_dir

pg0


打开分页机制


关于GDT

  • 1)boot_gdt

  • 2)per_cpu__gdt_page


关于堆栈stack_start


关于setup_idt

  • 在idt表中,填写ignore_int

  • 几个特殊的项:

输出如下信息:

输出如下信息:


装载GDT、IDT,进入3G地址空间


关于start_kernel

  • 对Linux内核的各个部分进行初始化

  • Start_kernel属于手工初始化的第一个进程(0号进程),该进程最后执行cpu_idle,成为idle进程

  • 系统创建的第一个进程(1号进程)

    • 该进程最后找到一个init程序进行Linux运行环境的初始化


upstart管理的ubuntu启动过程:

1,内核启动init

2,init找到/etc/event.d/rc-default文件,确定默认运行级别(X)

3,触发相应的runlevel事件,开始运行/etc/event.d/rcX

4,rcX运行/etc/init.d/rc,传入参数X

5,/etc/init.d/rc脚本进行一系列设置,最后运行相应的/etc/rcX.d/中的脚本

6,/etc/rcX.d/中的脚本按事先设定的优先级依次启动,直至最后给出登录画面(启动X服务器和GDM)

  • 若不想启动某程序,只要把相应的符号链接从/etc/rc2.d/中删去即可


Thanks!

The end.


  • Login