- 浏览: 427444 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
Glogo:
楼主您好,我在试验您的代码的时候发现新开的三个子线程并没有一直 ...
java 高并发 ReentrantLock -- 可重入的锁 -
univasity:
最近发觉也被限速了,投诉一下就好一会~~ 看来明天又要和电信M ...
ADSL上网速度慢 都是帐号限速惹的祸 -
liuyuanhui0301:
java 高并发 ReentrantLock -- 可重入的锁 -
dang_java:
呵.很好的说明文档.
JXTA技术与应用发展 -
helloqidi:
谢谢,学习了
SQL中exists和in的区别
一、系统引导过程总体介绍
启动流程图:
系统引导过程主要由以下几个步骤组成(以硬盘启动为例)
1、开机;
2、 BIOS加电自检(POST——Power On Self Test),包括检查RAM,keyboard,显示器,软硬磁盘等等。Intel系列的CPU首先进入的是实模式,并开始执行位于地址0xFFFF0处的代码,也就是ROM-BIOS起始位置的代码;
3、搜索启动的操作系统,根据BIOS设置,可能会依次访问每个软盘的第一个扇区、硬盘、CD-ROW等;一旦找到有效的启动设备,将第一个扇区(0头0道1扇区,也就是Boot Sector)的内容读入内存地址0x7c00处;
4、检查(WORD)0000:7dfe是否等于0xaa55.若不等于则转去尝试其他介质;如果没有其他启动介质,则显示 “No ROM BASIC” ,然后死机;
5、跳转到0000:7c00处执行MBR中的程序bootsect.S;
6、 MBR先将自己复制到0x90000处,然后将紧接其后的setup部分(第二扇区)拷贝到0x90200,将真正的内核代码拷贝到0x100000。以上这些拷贝动作都是以bootsect.S、setup.S以及vmlinux在磁盘上连续存放为前提的;
7、bootsect.S完成加载动作后,就直接跳转到0x90200,这里正是setup.S的程序入口。 setup.S的主要功能就是将系统参数(包括内存、磁盘等,由BIOS返回)拷贝到 0x90000-0x901FF内存中,这个地方正是bootsect.S存放的地方,这时它将被系统参数覆盖。以后这些参数将由保护模式下的代码来读取。
8、 setup.S还将video.S中的代码包含进来,检测和设置显示器和显示模式。最后,setup.S将系统转换到保护模式,并跳转到0x100000(对于bzImage格式的大内核是 0x100000,对于zImage格式的是0x1000)的内核引导代码,Bootloader过程结束;
9、Bootloader跳转到0x100000, 此处为"arch/I386/init/head.S"中的startup_32, startup_32的代码只需要设置一下全局变量,然后就跳转到start_kernel去了;start_kernel()是"init/main.c"中的asmlinkage函数,至此,启动过程转入体系结构无关的通用C代码中;
10、start_kernel()中设置与体系结构相关的环境、页表结构初始化、Trap/IRQ初始化、核心进程调度器初始化、时间/定时器初始化、控制台初始化、核心Cache初始化、内存初始化、内部及通用等各种Cache初始化、信号量初始化、其他部分初始化(Init()及smp_init());
11、启动Init()过程,创建第一个进程;Init()中,取得 run-level 信息, 执行 /etc/rc.d/rc.sysinit 脚本, 激活核心的外挂式模块 (/etc/modules.conf), 然后init 执行 run-level 的各个脚本, 接着执行 /etc/rc.d/rc.local脚本, 最后执行 /bin/login 程序, 登入之后开始以 Shell 控管主机;
12、启动完成。
bootsect.S,系统引导程序,一般不超过512字节。
在PC系统结构中,线性地址0xA0000以上,即640K以上用于图形接口卡和BIOS自身,640K以下为系统的基本内存。如果配置更多的内存,则0x100000,即1MB处开始称为高内存。当BIOS引导一个系统时,总是把引导扇区读入到基本内存地址为0x7c00的地方,然后跳转到此执行引导扇区的代码。这段代码将自身搬运到0x90000处,并跳转到那继续执行,然后通过BIOS提供的读磁盘调用“int 0x13”从磁盘上读入setup和内核映像。其中setup的映像读入到0x90200处,然后跳转到setup的代码中。
从0x90000到0xA0000一共64K,bootsect仅占512字节,所以setup大小理论上可到63.5KB。
在Linux2.4版本以前,在最前面的512字节里保护了一个mini “boot loader”,只要拷贝启动代码运行就可从软盘启动;但在2.6版本中不再保护这样的”boot loader”,所以必须在第一个磁盘分区上存储一个合适的boot loader才能从软盘启动,软盘、硬盘和光驱启动都是一样的过程。
setup进行映像的解压缩,从BIOS收集一些数据,在控制台显示一些信息。
基本内存中开头一部分空间是保留给BIOS自己用的,另一方面对于Linux内核的引导也需要保留一些运行空间,一共保存了64K。基本内存中用于内核映像的就是8*64K=512K,其中顶端留4K用于引导命令行及从BIOS获取需要传递给内核的数据。内核映像一般都经过压缩,压缩后的映像和引导扇区及辅助引导程序的映像拼接在一起,成为内核的引导映像。大小不超过508K的映像称为小映像zImage,早期版本放在0x10000位置处,否则称为大内核bzImage,放在0x100000位置处。
CPU在bootsect时处于16位实地址模式,然后在setup的执行过程中转入32位保护模式。
Setup从BIOS中读取系统数据(内存大小、显卡模式、磁盘等参数),将数据保存在0x90000-0x901FF,覆盖了bootsect的内容。设置32位运行方式:加载中断描述表寄存器IDTR、全局描述表寄存器GDTR;临时设置IDT表和GDT表,并在GDT表中设置内核代码段和数据段的描述符,在Head.S中会根据内核的需要重新设置这些描述符表;开启A20地址线;重新设置两个中断控制器8259A,将硬件中断号重新设置为0x20和0x2f;最后设置CPU的控制寄存器CR0(机器状态字)的保护模式比特(PE)位,从而进入32位保护模式运行;然后跳转到head.S中的startup_32执行。
对于小内核映像放在0x10000处,Setup会把system从0x10000移到0x0000开始处。对于大内核映像,vmlinux中普通内核代码被编译成以PAGE_OFFSET+1MB为起始地址,在Head.S中初始化代码把虚拟地址减去PAGE_OFFSET就能得到以1MB为起始位置的物理地址,这也正是内核映像在物理内存中的存放位置。
Head.S中的startup_32主要用于开启页面单元。初始化工作在编译过程中开始进行,它先定义一个称为swapper_pg_dir的数组,使用链接器指示在地址0x00101000。然后分别为两个页面pg0和pg1创建页表项。第一组指向pg0和pg1的指针放在能覆盖1~9MB内存的位置,第二组指针放在PAGE_OFFSET+1MB的位置。一旦开始页机制,在上述页表和页表项指针建立后可以保证,在内核映像中不论是采用物理地址还是虚拟地址,都可以进行正确的页面映射。内核其他部分的页表初始化在paging_init()中完成。映射建立后,通过设置cr0寄存器中的某位开启页面映射,然后通过一个跳转指令保证指令指针的正确性。
1.Bootsect启动过程:
假设用LILO启动,启动时用户可以选择启动哪个操作系统。LILO将boot loader分为两部分,一部分放到启动分区的第一个扇区;
1) BIOS将MBR或启动分区的第一个扇区的启动部分加载到地址0x00007c00处;
2) 该程序将自身移到0x00096a00,建立实模式栈(从0x00098000到0x000969ff),将LILO的第二部分加载到0x00096c00处,然后跳转到此执行;
3) 然后第二部分程序从磁盘读取一个可启动的操作系统列表让用户选择,最后用户选择每个OS后,boot loader可以拷贝不启动分区或者之间拷贝内核映像到RAM中去;
4) 加载Linux内核映像时,LILO boot loader首先调用BIOS例程显示”Loading …”信息;
5) 调用BIOS例程加载内核映像的初始化部分到RAM上,内核映像的前512字节放在0x00090000位置,setup()函数代码放在0x00090200位置;
6) 接着调用BIOS例程装载内核映像的其余部分,映像可能放在低地址0x00010000(使用make zImage编译的小内核映像)或者高地址0x00100000(使用make bzImage编译的大内核映像)。
7) 然后跳至刚刚setup部分。
2.Setup.S分析
setup()汇编函数被连接器放在内核映像文件中的0x200偏移处。Setup函数必须初始化计算机中的硬件设备并为内核程序的执行建立环境。
1) 在ACPI兼容的系统中,调用BIOS例程建立描述系统物理内存布局的表。在早期系统中,它调用BIOS例程返回系统可以的RAM大小;
2) 设置键盘的重复延迟和速率;
3) 初始化显卡;
4) 检测IBM MCA总线、PS/2鼠标设备、APM BIOS支持等;
5) 如果BIOS支持Enhanced Disk Drive Services (EDD),将调用正确的BIOS例程建立描述系统可用硬盘的表;
6) 如果内核加载在低RAM地址0x00010000,则把它移动到0x00001000处;如果映像加载在高内存1M位置,则不动;
7) 启动位于8042键盘控制器的A20 pin。
8) 建立一个中断描述表IDT和全局描述表GDT表;
9) 如果有的话,重启FPU单元;
10) 对可编程中断控制器进行重新编程,屏蔽所以中断,级连PIC的IRQ2不需要;
11) 设置CR0状态寄存器的PE位使CPU从实模式切换到保护模式,PG位清0,禁止分页功能;
12) 跳转到startup_32()汇编函数, jmpi 0x100000, __BOOT_CS,终于进入内核Head.S;
3.Head.S分析
有两个不同的startup_32()函数,一个在arch/i386/boot/compressed/head.S文件中,setup结束后,该函数被放在0x00001000或者0x00100000位置,该函数主要操作:
1) 首先初始化段寄存器和临时堆栈;
2) 清除eflags寄存器的所有位;
3) 将_edata和_end区间的所有内核未初始化区填充0;
4) 调用decompress_kernel( )函数解压内核映像。首先显示"Uncompressing Linux..."信息,解压完成后显示 "OK, booting the kernel."。内核解压后,如果时低地址载入,则放在0x00100000位置;否则解压后的映像先放在压缩映像后的临时缓存里,最后解压后的映像被放置到物理位置0x00100000处;
5) 跳转到0x00100000物理内存处执行;
解压后的映像开始于arch/i386/kernel/head.S 文件中的startup_32()函数,因为通过物理地址的跳转执行该函数的,所以相同的函数名并没有什么问题。该函数未Linux第一个进程建立执行环境,操作如下:
1) 初始化ds,es,fs,gs段寄存器的最终值;
2) 用0填充内核bss段;
3) 初始化swapper_pg_dir数组和pg0包含的临时内核页表:
l 将swapper_pg_dir(0x1000)和pg0(0x2000)清空,swapper_pg_dir作为整个系统的页目录;
l 将pg0作为第一个页表,将其地址赋到swapper_pg_dir的第一个32位字中。
l 同时将该页表项也赋给swapper_pg_dir的第3072个入口,表示虚拟地址0xc0000000也指向pg0。
l 将pg0这个页表填满指向内存前4M。
l 在cr3寄存器中存放PGD的地址,并设置cr0寄存器中的PG位,启用分页支持。
4) 建立进程0idle进程的内核模式的堆栈;
5) 再次清除eflags寄存器的所有位;
6) 调用setup_idt()用非空的中断处理函数填充IDT表;
7) 将从BIOS获取的系统参数传递到操作系统的第一个页面帧;
8) 识别处理器的模式;
9) 将GDT和IDT表的地址加载到gdtr和idtr寄存器中;
10) 跳转到start_kernel函数,这个函数是第一个C编制的函数,内核又有了一个新的开始。
4.start_kernel()分析:
1) 调度器初始化,调用sched_init();
2) 调用build_all_zonelists函数初始化内存区;
3) 调用page_alloc_init()和mem_init()初始化伙伴系统分配器;
4) 调用trap_init()和init_IRQ()对中断控制表IDT进行最后的初始化;
5) 调用softirq_init() 初始化TASKLET_SOFTIRQ和HI_SOFTIRQ;
6) Time_init()对系统日期和时间进行初始化;
7) 调用kmem_cache_init()初始化slab分配器;
8) 调用calibrate_delay()计算CPU时钟频率;
通过调用kernel_thread()启动进程1init进程的内核线程,然后该线程再创建其他的内核线程执行/sbin/init程序。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/cxylaf/archive/2007/05/26/1626513.aspx
发表评论
-
Linux的tmpfs文件系统
2012-05-02 17:46 7183前几天发现服务器的内存(ram)和swap使用率非常低,于是就 ... -
iostat来对linux硬盘IO性能进行检测
2012-03-22 18:11 1007近期公司安装了几台DELL ... -
Softlinks vs. Hardlinks: A Quick Explanation
2012-01-18 15:04 1272I got this question in an ema ... -
查看linux 线程
2011-11-22 11:35 884查看linux 线程 博客分类: linux ... -
Linux学习总结—缺页中断和交换技术
2011-05-18 11:00 2548三、Linux缺页中断处理1.请求调页中断:进程线性地址空间里 ... -
Linux学习总结—Linux调度器分析
2011-05-18 10:58 1690四、Linux调度器分析1.Linux2.6调度器的特性2.6 ... -
Linux内存分段和分页管理
2011-05-18 10:56 21131.x86 内存架构和Linux的分段管理x86 内存架构在 ... -
Linux自动启动服务
2010-09-23 13:08 955linux自动启动服务很简单,最简单的是把启动命令放到/etc ... -
linux设置ip.dns.gateway
2009-06-11 15:05 1948静态方法注意:所有操作均使用root用户 #ifcon ... -
自己如何制作RPM包
2009-05-21 14:39 1718我最早使用redhat就是冲 ... -
RPM包rpmbuild SPEC文件深度说明
2009-05-21 14:28 1810上一篇日志写到,为什么要制作rpm包,以及如何使用.src.r ... -
调整swap分区大小
2009-02-10 16:51 1876方法一:如果磁盘有剩余的空间,用分区工具新建一个swap分区. ... -
非常实用的Ubuntu命令大全
2008-12-03 15:05 1310非常实用的Ubuntu命令大全 ... -
Linux操作系统上Lsof命令详解
2008-12-03 14:33 1328一般root用户才能执行lsof命令,普通用户可以看见/u ... -
DOS/Windows和Linux/Unix间的文件格式转换
2008-12-03 11:15 1953DOS/Windows和Linux/Unix间 ... -
syntax error: unexpected end of file
2008-12-03 11:02 3665dos文件转换成unix文件格式 dos格式文件传输到u ... -
BASH中getopts的用法
2008-12-02 15:22 1522getopts optstring varname [arg ... -
正则表达式之grep
2008-07-10 19:21 2435grep 的名称实际上就来 ... -
Linux基本命令
2008-07-10 18:31 1283进入Linux系统:必须要输入用户的账号,在系统安装过程中可以 ... -
Linux文件系统
2008-07-10 18:27 9431、Linux文件系统是从/开始的 在Linux操作系统 ...
相关推荐
在深入探讨ARM Linux启动分析之前,首先需要理解Linux操作系统的基本启动流程和ARM架构的特点。Linux启动过程主要分为两个阶段:Bootloader阶段和内核启动阶段。Bootloader是系统上电后执行的第一段程序,它的主要...
### ARM Linux启动分析 #### 1.5 Armlinux启动分析概述 Armlinux的启动过程是一个复杂且精细的过程,涉及到多个阶段的协同工作。在深入解析Armlinux的启动流程之前,首先需要理解ARM体系结构的基本概念及其与Linux...
【ARM Linux 启动分析】 在嵌入式领域,Linux操作系统因其开源、高效和灵活性而广泛应用,尤其是在基于ARM架构的设备上。ARM Linux启动过程涉及多个关键组件,其中最主要的是bootloader和Linux内核。本篇文章将深入...
### ARM Linux启动分析 #### 一. Bootloader 在Alpha/AXP平台上引导Linux有两种主要的方法:一是通过MILO或其他类似引导程序引导;二是通过Firmware直接引导。MILO类似于i386平台上的LILO,它内置了基本的磁盘驱动...
Linux启动分析专题 在深入探讨Linux启动过程之前,我们首先要理解操作系统的作用,它是一个管理计算机硬件资源并为用户和应用程序提供服务的系统软件。Linux,作为一款开源的类Unix操作系统,其启动流程涉及多个...
《基于AT91RM9200的Linux启动分析》这篇文章主要探讨了在基于AT91RM9200芯片上Linux操作系统的启动过程。AT91RM9200是一款由Atmel公司基于ARM架构设计的处理器,由于其内置网络控制器和高效能,被广泛应用在嵌入式...
ARM Linux系统的启动过程是一个复杂而有序的序列,它涉及到Bootloader、硬件初始化、内核加载以及内核自身的初始化等多个步骤。下面将详细分析这个过程。 首先,Bootloader是系统启动的第一步,它负责加载内核并做...
### ARM + Linux 启动分析(zImage) #### 摘要 本文旨在深入解析基于ARM架构的Linux 2.2.26内核启动流程,重点在于zImage压缩内核映像的启动机制。文章从`/arch/arm/Makefile`入手,介绍了Linux内核的三种启动...
标题与描述概述的是关于ARM Linux启动过程的深入分析,特别是针对Bootloader的作用及其与内核交互的机制。本文档将详细解析ARM Linux启动的关键步骤,包括Bootloader的职责、初始化流程,以及内核启动的各个阶段,...
Linux启动分析是理解操作系统核心运行机制的关键步骤,它涉及到内核加载、初始化、硬件设备的探测与驱动程序的加载等多个环节。在这个过程中,系统从BIOS(基本输入输出系统)过渡到Linux内核,再到用户空间的应用...
在深入分析ARM Linux启动流程时,我们首先要了解的是,Linux操作系统在硬件启动后的第一步是执行arch/arm/kernel目录下的head-($PROCESSOR).S文件,这里的$PROCESSOR代表CPU的具体类型。对于ARM架构,从ARM6开始,...
《ARM+Linux启动分析——以zImage为例》 在嵌入式系统中,尤其是基于ARM架构的设备,Linux内核的启动方式对于系统的整体性能和资源利用率至关重要。本文主要聚焦于ARM架构下Linux 2.2.26内核的启动过程,特别是压缩...
### Linux启动流程分析 #### 一、Bootloader启动内核过程 Linux系统启动时的核心流程之一便是由Bootloader引导内核。在这个过程中,Bootloader负责完成一系列基础设置,并最终将控制权交给内核。以下是对...
### Linux ARM 启动分析:汇编部分深入探讨 #### 引言 在探索Linux操作系统在ARM架构上的启动过程时,我们聚焦于汇编语言层面的解析,这是一段复杂而精妙的旅程,旨在理解从裸机环境到功能完备的操作系统内核的...
Linux 启动 bootargs 参数分析 在 Linux 启动过程中,bootargs 参数扮演着重要的角色,该参数用于传递启动选项和配置信息给内核。Linux 内核在启动时对 bootargs 参数的解析可以分为两大块:setup_arch 函数和 ...
linux2.6内核启动分析
《深入解析ARM+Linux启动分析:以zImage为例》 在嵌入式系统的世界中,ARM架构因其低功耗和高性能的特点,成为许多设备的心脏。Linux操作系统则以其开源、稳定和灵活性,成为ARM平台的首选操作系统。然而,理解...