系统引导过程总体介绍

系统引导过程主要由以下几个步骤组成(以硬盘启动为例)
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 程序。

 

 

转载于:https://my.oschina.net/alphajay/blog/5103

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
linux操作系统 一、单项选择题 1. 关于Linux内核版本的说法,以下错误的是()。 A.表示为主版本号.次版本号.修正号 B.1.2.3表示稳定的发行版 C.1.3.3表示稳定的发行版 D.2.2.5表示对内核2.2的第5次修正 2. 系统引导过程一般包括如下几步: a.MBR中的引导装载程序启动; b.用户登录; c.Linux内核运行; d.BIOS自检。 正确的顺序是()。 A.d,b,c,a B.d,a,c,b C.b,d,c,a D.a,d,c,b 3. 字符界面下使用shutdown命令重启计算机时所用的参数是()。 A.-h B.-t C.-k D.-r 4. 下面哪个不是桌面环境软件? A.KDE B.twm C. Gnome D.CDE 5. 在UNIX/Linux系统添加新用户的命令是() A. groupadd B. usermod C. userdel D. useradd 6. Android系统是基于Linux操作系统开发的手机系统,因此在进行刷机、删除系统自带软件时需要获得管理员账户( )的权限。 A.administrator B.admin C.root D.liveuser 7.已知当前系统umask的值为022,请问这时新建目录文件的权限为()。 A. 755 B. 644 C.775 D.664 8.已知用户sarwar在虚拟终端1和虚拟终端2及图形用户界面下登录,请问sarwar在虚拟终端1中执行ls >tty2后,命令输出到哪里?() A.虚拟终端1 B.虚拟终端2 C.图形终端 D.无输出 二、填空题(每空1分,共15分) 1. Linux系统中有三种基本的文件类型:普通文件、目录文件和 设备文件 。 2. 在超级用户下显示Linux系统中正在运行的全部进程,应使用的命令及参数是 ps -aux 。 3. 将前一个命令的标准输出作为后一个命令的标准输入,称之为 管道 。 4. /sbin 目录用来存放系统管理员使用的管理程序。 5. 安装Linux系统对硬盘分区时,必须有两种分区类型: 文件系统分区 和 交换分区 。 11.将/home/stud1/wang目录做归档压缩,压缩后生成wang.tar.gz文件,并将此文件保存到/home目录下,实现此任务的tar命令格式__ __tar -czvf wang.tar.gz /home/stud1/wang_ 三、判断题(每题1分,共10分) 1. Ubuntu LINUX安装时自动创建了根用户。( T ) 2. LINUX中的超级用户为root,登陆时不需要口令。( F ) 3. Linux不可以与MS-DOS、OS/2、Windows等其他操作系统共存于同一台机器上。( F ) 4. Linux的特点之一是它是一种开放、免费的操作系统。 ( T ) 5. RedHat系统中,默认情况下根口令没有字符长短的的限制,但是必须把口令输入两次;如果两次输入的口令不一样,安装程序将会提示用户重新输入口令。 ( F ) 四、问答题\应用操作题(每题5分,共25分) 1. Linux内核主要由哪几部分组成?每部分的作用? Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信。 进程调度(SCHED):控制进程对CPU的访问。当需要选择下一个进程运行时, 由调度程序选择最值得运行的进程; 内存管理(MM)允许多个进程安全的共享主内存区域; 虚拟文件系统(VirtualFileSystem,VFS)隐藏了各种硬件的具体细节,为所有的设备提供了统一的接口,VFS提供了多达数十种不同的文件系统; 网络接口(NET)提供了对各种网络标准的存取和各种网络硬件的支持; 进程间通讯(IPC) 支持进程间各种通信机制。 2. vi编辑器有哪几种工作模式?如何在这几种工作模式之间转换? Vi的工作模式有三种:命令模式、输入模式、末行模式。 在命令模式下输入a、A、i、I、o、O等命令之一可以进入输入模式, 在输入模式下按Esc键回到命令模式; 在命令模式下输入:进入末行模式,末行命令执行完后回到命令模式。 3.假设你是系统管理员,需要增加一个新的用户账号u1,为新用户设置初始密码,锁定用户账号u2,并删除用户账号u3。请写出完成本题所述功能的命令序列 useradd u1 -添加用户u1 passwd 123456 -为用户添加密码123456 passwd -l u2 -锁定用户账号u2 userdel u3 -删除用户账号u3 4.写出将/abc目录中所有文件及目录打包压缩成文件abc.tar.gz的命令。 tar -zcvf abc.tar.gz /bc 5.创建一个用户,用户名为user02,所属私有组和标准组为group01,用户主目录为/home/user02,用户登录shell为/bin/bash。 useradd -g group01 –G group01 –d /home/user02 -s /bin/bash user02 五、综合题(1题10分,1题10分,共20分) 1、已知管理员用户的主目录结构如图2所示: (1)管理员用户目前在/R/B/T4/S0中,分别写出执行以下命令后,管理员在目录系统中的位置。 cd /R cd .. /R/B/T4 cd ../.. /R/B cd / / cd ~ /R (2)写出删除目录C的两种办法。 1.rm -rf /root/C 2.rm /root/T3 rm /root/T4 rmdik/root/C (3)已知管理员用户在/R目录中,分别用绝对路径和相对路径方式写出将目录/R/C/T3/S0中的文件复制到/R/D/T5目录中的方法。 cp /R/C/T3/S0 /R/D/T5 cp /C/T3/S0 /D/T5 2、设计一个shell程序计算n的阶乘。要求: (1) 从命令行接收参数n; (2) 在程序开始后立即判断n的合法性,即是否有参数,若有是否为正整数,若非法请给错误提示; (3) 最后输出计算的结果。 #!/bin/sh echo “please input your number n:” read n #if(( ! -n “$n”)); then if test -z “$”; then echo “n is no data !” exit 1 else if(( $n<=));then echo -e “$n is no zhengzhengshu.\n”; exit 1 fi fi fact=1;tmp=1 while[$tmp -le $n ] do fact=$((fact*tmp));tmp=$((++tmp)); done echo "fact=$fact"

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值