Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2084408
  • 博文数量: 414
  • 博客积分: 10312
  • 博客等级: 上将
  • 技术积分: 4921
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-31 01:49
文章分类

全部博文(414)

文章存档

2011年(1)

2010年(29)

2009年(82)

2008年(301)

2007年(1)

分类: C/C++

2008-04-26 12:23:34

史前时代:BIOS
-->开机
-->启动加电-->触发CPU引脚生成RESET值
-->设定(cs、eip等)寄存器为固定值
-->在0xfffffff0(ROM)处找到代码来执行
-->ROM程序集(在80x86体系中叫做BIOS)中运行
-->对计算机执行一系列的测试
-->初始化硬件设备
-->搜索一个操作系统来启动
-->只要找到一个有效设备,就把第一个扇区中所存放的指令装载到RAM中从物理地址0x00007c00开始的位置,让后跳转到这个地址处,开始执行刚才装载进来的代码
 
远古时代:引导装入程序
-->使用小程序加载指令集到RAM中(WINDOWS用MBR(带ACTIVE标志的小程序);LINUX用LILO或者是GRUB)
-->LILO的第一步,MBR或者分区引导扇区包括一个小的程序引导装入程序,BIOS把这个小程序装入从地址0x00007c00开始的RAM中,接着把自己移动到0x00096a00
-->建立实模式栈(0x00098000~0x000969ff),并把第二部分的内容装入到从地址0x00096c00开始的RAM中
-->给出用户提示符,给定时延时间,然后决定启动用户选择的内核或者是默认的内核
-->调用BIOS,显示LOADING。。信息
-->调用BIOS将内核映像的第一个512字节从地址0x00090000开始存入RAM中
-->将setup()代码从地址0x00090200开始存入RAM中
-->把内核的剩余映像放入0x00010000(make zimage)或者0x00100000(make bzimage)开始的ram中,分别成为“低装载”或者“高装载”
-->跳转到setup()
 
中世纪:setup()函数
-->ACPI兼容的系统中,它调用一个BIOS例程,以在RAM中建立系统物理内存布局表("IOS-e820")调用BIOS,返回系统可用内存
-->设置键盘重复时延和速率
-->初始化视频卡
-->重新初始化磁盘控制器并检测硬盘参数
-->检查微通道总线
-->检查PS/2指针设备
-->检查对高级电源管理器(APM)BIOS的支持
-->(BIOS支持增强磁盘驱动服务EDD,调用相应的BIOS过程在RAM中建立系统可用硬盘表(/sys/firmware/edd目录))
-->内核低装载在0x00010000处,把它移动到0x00001000处;如果是高装载,不移动
-->为了与古老的8088微处理器物理地址兼容,置位8042键盘控制器的A20引脚装载的程序在启动的过程中被执行
-->建立临时中断描述符表IDT和一个临时全局描述符表GDT
-->重置浮点单元FPU
-->重新编写可编程中断控制器PIC,以屏蔽所有中断,但保留IRQ2
-->通过设置cr0状态寄存器中的PE位,把CPU从实模式切换到保护模式,cr0状态寄存器中的PG位被清0,因此分页还没有启用
-->跳转到startup_32()函数
-->LINUX进入保护模式,脱离BIOS,对各个设备加载相应的驱动
 
文艺复兴时期:startup_32()函数
 
arch/i386/boot/compressed/head.S文件中,第一个startup_32()函数
-->startup_32()函数,arch/i386/boot/compressed/head.S文件中实现。setup()结束之后,startup()就已经被移动到物理地址0x00100000处或者0x00001000处
-->初始化段寄存器和一个临时堆栈
-->清零eflags寄存器的所有位
-->以0填充由_edata和_end符号表示的内涵未初始化数据区
-->解压decompress_kernel()函数来解压内核映像。显示"Uncompressing Linux ..."解压后,显示"OK,booting the kernel"
-->解压后的内核映像放置在0x00100000处,如果高装载,放在位于这个压缩映象之后的临时缓冲区,然后解压后的映像被移动到从物理地址0x00100000开始的最终位置
-->跳转到物理地址0x00100000处
 
arch/i386/boot/compressed/head.S文件中,第二个startup_32()函数,为第一个LINUX进程(进程0)建立执行环境
-->段寄存器初始化为最终值
-->把内核的bss端填充为0
-->初始化含在swapper_pg_dir的临时内核页表,并初始化pg0
-->把页全局目录的地址存放在cr3寄存器中,并通过设置cr0寄存器的PG位启用分页
-->为进程0建立内核状态堆栈
-->该函数再一次清零eflags寄存器的所有位
-->调用setup_idt()用空的中断处理程序填充IDT
-->把BIOS中获得的系统参数和传递给操作系统的参数放入第一个页框中
-->识别处理器的型号
-->用GDT和IDT表的地址来填充gdtr和idtr寄存器
-->跳转到start_kernel()函数
 
start_kernel()函数完成Linux内核的初始化工作
-->调用sched_init()函数来初始化调度程序
-->调用build_all_zonlists()函数来初始化内存管理区
-->调用page_alloc_init()函数来初始化伙伴系统分配程序
-->调用trap_init()函数和init_IRQ()函数以完成IDT初始化
-->调用softirq_init()函数来初始化TASKLET_SOFTIRQ和HI_SOFTIRQ
-->调用time_init()函数来初始化slab分配器
-->调用calibrate_delay()函数以确定CPU时钟的速度
-->调用kernel_thread()函数为进程1创建内核线程,这个内核线程又会为我们创建其他的内核线程并执行/sbin/init程序
 
-->在start_kernel()开始执行之后会显示"Linux version 2.6.22....."信息
-->显示用户登录提示符
阅读(1042) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~