论坛风格切换切换到宽版
  • 978阅读
  • 0回复

[问题求助]understand grub [复制链接]

上一主题 下一主题
离线douxp.
 
发帖
2188
C币
-193049
威望
401
贡献值
1
银元
0
铜钱
4922
人人网人气币
0
只看楼主 倒序阅读 使用道具 楼主  发表于: 2009-05-01

grub就是引导程序,引导不同的操作系统。这是他的功能,但是具体是怎么引导的呢?最.好的办法就是.看代码。投资

深入代码之前先要有个整体了解,否.则看代码会很晕的。都不知道第一个指.令在哪。           建材

grub启动方式:
1)直接引导方式
   通过root指定引导文件的位置,k.er.ner加载引导文件。(广告)
2)链式引导方式
主要步骤如下:
(1) 通过'rootnoverify'命令.设置GRUB的主设备指.向一个扇区。           婚庆
g.ru.b> rootnoverify (hd0,0) [成人用品]
(.2) 通.过'makeactive'命令来设置在扇区上的'active’标志位。 .
grub>. makeactive .
(3) 通过'.chainloader'命令来加载引导程序.。              汽车
grub> .chainloader +1 --------------彩票
'+1'.表明GRUB需要从起始分区读一个扇区。 电脑
(4) 运行命令'boot'
GR.UB引导操作系统的简要流程分析外贸
3.2.1 从计算机启动到GRUB启动操作系统.     健康
(1) BIOS执行INT 0x19,加载MBR至0x7c00并跳转执行。如果你安装GRUB到MBR,GRUB的安装程序会把Stage1(512B)拷贝到MBR。视stage2的大小,安装程序会在 S.tage1中嵌入Stage1.5或者Stage.2的.磁盘位置信.息。           婚庆
(2) S.tage1开始执行,它在进行直接加载Stage1_5或者Stage2并跳转执行。不论是哪种情况,这一步的结果都是Sta.ge2开始运行了。 虚拟主机
(3) Stage2这个小型的操作系统终于开始正式运行了!它会.把.系统切入保护模式,设置好C运行环.境(主要是BSS)。他会先找Config文件(就是.我们的 Menulist),如果没有的话就执行一个Shell,等待我们输入命令。然后Grub的工作就是输入命令-解析命令-执行命令的循环,当然 Stage2本身是为加载其他操作系统而存在的,所以如果情况允许,在他执行Boot命.令以后就会把控制权转交出去。.
3.2.2.  GRUB的主要启动模块 .
GRUB 包含如下几个启动模块:两个必须的场景文件,一个叫"Stage 1..5"的可选的 场景文件以及2个网络启动的映像文件。首先对他们有一.个.大致的了解。              汽车
Stage1
这是一个基本必须的用.来启动.GRUB的映像文件。通常,这个文件是被装载到MBR或者启动扇区所在的分区。由于PC的启动扇区的大小为512字节.,所以这个映像文件编译以后也必须为512字节。 域名
Stage1的全部的工作是从.本地磁盘把Stage 2或者Stage 1.5装载进来。由于对 stage1大小的限制,它通过分程序表的形式来编码Stage 2或者Stage 1..5的位置,所以在stag.e1是不能识别任何文件系统的。 --------------彩票
Stage2
这是GRUB的核心映像。它几乎做了除启动它本身以外的所有事情。通常,它被存放为某一种文件系统下,但并非.是必须的。. .
e2fs_stage1_5
fat_stage1_5
ffs_stage1_5
jfs_stage1_5
minix_stage1._5 健康
reiser.fs_stage1_5 .
v.stafs_stage1_5 .
xfs_stage1_5
这些文件被称为..stage 1.5,它存在的目的是做为stage1与stage2之间的桥梁,也就是说,stage1.载入stage1.5,然后stage1.5载入 stage2。
st.age1与stage1.5之间的区别是.,前者是不识别任何文件系统的但后者识别文件系统(例如 'e2fs_stage1_5' 识别 ex.t2fs)。所以你可以安全的移动stage2的位置,即使是在GRUB安装完以后。              电子
nbgrub
这是.一个网络启动的映像文件,被类似于以太网启动装载器所使用。它很类似于stage2,但它还要建立网络,然.后通过网络来载入配置文件[7]。            鲜花
pxegrub
这是另一个网络启动的映像文件。.             杀毒
除了格式以外,它和'nbgrub'.是一致的。 服务器
4 STAGE1模块分析
Stage1模块是整个引导程序的引导模块,是从开机过渡到GRUB的第一个模块。 Stage1的代.码文.件,是源码目录下 Stage1/Stage1.S,汇编后便成了一个5.12字节的Img,被写在硬盘的0面0道第1扇区,作为硬盘的主引导扇区。            女人

4.1 Stage1.h文件分.析 --- 印刷
在此文件中主要是定义了一些在St.age1.S文件中使用到的一.些常量。 <性病>
关于这些常量的分析如下:
/* 定义了grub的版本号,在sta.ge1中可以识别他们..*/             杀毒
#define COMPAT_VER.SION_MAJOR. 3 .
#define COM.PAT_V.ERSION_MINOR 2 --------------彩票
#define COMPAT_VERSION ((.COMPAT_VERSION_MINOR 由于对Stage1文件容量的限制,所以Stga..e.1所做的工作相对来说比较有限。它首先被BOI.S装载到内存中的0x7c00处,然后通过调用BOIS INT13中断,把启动驱动器中第二扇区上的内容读到内存中的0x7000处,然后通过调用COPY_BUFFER将其转移到了内存中0x8000的位置上。这个被读入.的第二扇区上的内容,就是下面将要分析的Start.s功能模块。 (广告)
5  START模块分析
从上一章节的分析.中我们看到,Stage1的是完成了一个MBR所需要完成的任务,.但 GRUB并没有直接就通.过Stage1直接载入GRUB的内核,而.是通过Stage1载入了另一个 模块到0x8000处。根据对源代码的分析,发现被载入的这个模块就是下面需要分析 的第二个模块,即Start.S模块。 .
5.1 Start.s 模块功能.分析            建材
在程序的开始部分,仍然.是对程序定义了一些宏。 教育
#ifdef .STAGE1_5 .
# define ABS(x) (x-_.start+0.x2000)              电子
#else
#. define ABS(x) (.x-_start+0x8000) .
#endif
可.以发现,如果定义了STAGE1_5则程序的起始地址是0x2000,而如果没有定义 STAGE1_5程序起始的地址正好是0x8000。所以我判断,在Stage1后载入内存的程序部.分就是Start..s所编译以后的5.12字节的映象文件。关于STAGE1_5的部分暂时先不进行分析,这里暂且跳过。 学习
宏 “#d.efine MSG(x) movw $ABS(x), %si;”的作用是在.屏幕上显示字符串。              汽车
接着就是.程序的入口_start。由于是紧接着Stage1被载入内存中的,所以它的起始 地址就是0x8000,并且它仍然将使用St.age1模块.留下来的寄存器以及变量等信息。 如果设置STAGE1_5变量则在屏幕上显示“Loading stage1...5”,如果没有设置这个变 量则显示“Load.ing stage2”。然后读入需要读入的扇区的数目.。接着进.入一个 bootloop的循环,如果需要读.入的扇区不为0,.则继续循环,直到当需要读入的扇 区数目为0时,循环结束。在这个循环中,使用与Stage1中的方法相同,判断了驱 动器磁盘所支持的读写模式,根据不同的磁盘所支持的不同模式,跳转到相应的部 分去读取磁盘上的扇区到内存中去。如果磁盘支持的是LBA模式则跳转到lba_mode 部分读取相应的扇区,如果磁盘不支持LBA模式,则跳转到 chs_mode部分,.通过 CHS模式来读入把磁盘中的扇区读入到内存中。首先是把读到的扇区读到内存中的. 0x7000处缓存起来,然后通过调用 copy_buffer子程序,把缓存中的内容复制到目 标地址,即0x8200开.始的地方。与Stage1中的一样,在Start.s中也有一个记录地址的数据结构,不同的是在Stage1中只有一项,而Start.S记录的是一个地址的链表,称为Blocklist,该链表的结点都记录了一个连续 sectors的集合。               乙肝
lastlist:
.word 0
.word 0
. = _start + 0.x200 - BOO.TSEC_LISTSIZE 外贸
/*加0x200.是由于Sta.rt.s编译完以后也是一个512字节的映象文件。*/ 电影
/* 初始化了第一个数据列表*./           婚庆
blocklist_defau.lt_start: 虚拟主机
.long 2 /* 记录了从第3个.扇区开始*/ 健康
blocklist_de.fault_len: .
/* 这个.参数记录了需要读取多少个扇区 */ 学习
#.ifdef STAGE1_5 学习
..word 0 /* 如果设置了S.TAGE1_5标志,则不读入*/     健康
#else
.word (STAGE2_SIZE .+ 511) >> 9 /*读入.Stage2所占的所有扇区*/ (        游戏          )
#endif
blocklist_default_.seg: <性病>
#.ifdef STAGE1_5
..word 0x220 /*如果设置STAGE1_5则从0x220开.始读入*/ .
#else
.word 0.x820 /*如果没有设置STAGE1_5则从0x820开始读入*./     美容
#endif
firstlist:
当把所有需要读入的扇区都读入以后,程序进入bootit子程序块。然后程序进行跳转.,如果设置了S.TAGE1_5标志,则跳转到0x2200执行,如果没有设置S.TAGE1_5标志,则跳转到0x8200处继续执行。 --- 印刷
5.2 Start. 模块功能综述 电脑
通过对Start.s文件的分.析,我们可以看到。Start模块主要是做了一件事情,就是把Stage2或者Stage1_5模块从磁盘装载到内存中。如果是直接装载Stage.2的话,是装载在内存的0x8200处,如果装载Stage1_5.的话,是装载在.内存的0x2200处。 .
6  GRUB Kernel模块分析 .           建材
由于我分析的是GRUB2的源代码,从GRUB2开始,从Start模块载入的是Grub的整个 kern.el。从官方的说明可以看到,与Gr.ub相比,最大的差异在于GRUB2将Stage1.5 以及Stage2的功能归并为GRUB2的kernel,并提高了压缩性能;编译生成的 kernel──core.img只有24KB左右,即使对于最普遍的CHS读写模式所支持的0面0道 的64个扇区(折合32K左右.)而言,空间是足够放置.GRUB2的kernel的,.Grub的每个 Stage1.5都至少在11K左右,而stage2则为1.10K左右。            女人
6.1 Asm.s. 文件分析 .
在分析了Start模块以后,发现如果没有设置Stage1_5参数,那么系统已.经把Grub. kernel从磁盘完全装载到了起始地址为0x8200开始.的.内存中。于是我便在源代码中 寻找起始地址从0x8200开始执行的代码。发现Asm.s文件就是这样一个符合条件的 模块。 <性病>
首先在这个文件的开始,仍然定义.了这样一个宏:               乙肝
#ifdef STA.GE1_5     美容
# define ABS(x.) ((x) - EXT_C(mai.n) + 0x2200) 域名
#else
# define ABS(x) ((.x) - EXT_C(main.) + 0x8200) 外贸
#endif
从这个宏中可以看出,从Start.模块以后从磁盘转载的应该就是这个文件编译以后的模块。程序的入口是EXT_C(main)。如果没有定.义 STAGE1_5那么程序的起.始地址 正是0x8200完全符合前面所做的分析。同时由于设置了.code16,整个程序开始仍然.是工作在实模式下的。
接着分析ENTRY(main)这个函数。首先为了保证main这个函数如果是Stage2的.话被装.载在0x8200,如果是Stage1.5的话被装载在0x2200。然后程序执行了一个长跳转。ljmp $0, $ABS(c.odestart)。 .
在执行codestart代码之前.,它对一些变量进行了初始化。设置了如版.本号、 install_partition、saved_entryno、 stage2_id、force_lba和config_fil.e等。 如果是Stgae1.5则config_file为 “/boot/grub/stage2”,如果.是Stage2则为 “boot/grub/menu.l.st”。 外贸
然后进入codestart代码,首先关中断,对断寄存器进行了一些初始化,然后设置了.堆栈的起始地址为STACKOFF即(.0x2000 - 0x10)。 --- 印刷
接着程序调用了real_to_pro.t这样一个子功能模块。从实模式转换.把程序转换到保护模式下。           建材
分析ENTRY(re.al_to_prot)子功能,主要的转.换步骤如下:    外汇
首先程序仍然在实模式下,关中断。接着载入了GDT表。然后通过.code32转到保护模式下,.跳转到protcseg.子功能下,重新装载所有的段寄存器。同时把返回的地.址放到 STAC.KOFF中,然后获得保护模式下的堆栈地址,把STACKOFF压入堆栈中,进行保护。然后返回。外贸
然后程序继续,清空了bss段,调用了init_bios_info函数,这个函数体是整个C语言.代码的入口.,是C main函数前的初始化代码。 .
在asm.s文件中,主.要是一些汇编代码的函数块,没有C语言的代码,.于是我在 share.h中找到了init_bios_info的函数定义,从而在 common.c中找到了 in.it_bios_info的代码。 外贸
同时在这个文.件中还定义了非常多的汇编代码写的函数,这些函数将来会被C文件 调用。这里.先对这些文件进行一下说明,如表6.1所示。 域名
表6.1 asm.s文件中的汇编函数列.表 电脑
函数名称 函数作用
stop() 调用prot._to_real子函数,从保护.模式转换成实模式     美容
har.d_stop() 通过反复调用自身,形成一个.死循环,起到一个暂停的作用     美容
grub_reboot() 重新启动.系统           婚庆
grub_halt(int no_apm). 暂停系统,利用时钟计时,如果设置NO_APM.将不使用时钟计时 教育
tr.ack_int13(int drive) 追踪INT13来操作I/O.的地址空间 .
set_int1.5_handler(void) 建立INT15的句柄. .
unset_int15_han.dler(void) 重新恢复INT15的句柄. 电影
set._i.nt13_handler(map) 复制一块数据到驱动器并且建立INT13的句柄 .
chain_stage1(segment,offset,part_table_ad.dr) 启动另一个stage1的.载入程序 --- 印刷
chai.n_stage2(segment, offset, second_sec.tor) 启动另一个stage2的载入程序 .
r.eal_to_prot () 实模式转换成保护.模式     美容
prot_to_rea l() 保护模式转换成.实模式. .
i.nt biosdisk_int13_extensions (in..t ah, int drive, void *dap) 调用IBM/MS 扩展INT13的功能。 (广告)
int biosdisk_stan.dard (int ah, int drive, int coff,int hoff., int soff,int nsec, int segment) 调用标准的I.NT13功能 域名
int .check_int13_extensions (int drive). 检查磁盘是否支持LBA模式            鲜花
get_diskin.fo_int13_extensions (int drive, void *drp) 从参数*drp.返回磁盘 驱动的具体结构 服务器
int get_diskinfo_standard (i.nt drive, unsigned long *cylinders,unsigned lon.g *heads, unsigned long. *sectors) 返回指定磁盘的柱面,磁头.以及扇区信息 .
int get_diskinfo_floppy (int drive, u.nsigned long *cylinders,unsigned long. *heads, unsigned long *se.cto.rs) 返回软盘的磁盘的柱面,磁头以及扇区信息           婚庆
get_code_end() .返回代码末端的地址               乙肝
get_memsi.ze(i) 返回内存大小,如.果I为0返回常规内存,I为1返回扩展内存            鲜花
get_eisamem.size() 返回EISA的内.存分布图 <性病>
g.et_rom_config_ta.ble() 获得Rom配置表的线性地址               乙肝
int get_vbe_controller_info (struct vbe._co..ntroller *controller_ptr) 获得 VBE控制器的信息            建材
int get_vbe_mode_inf.o (int mode_number, struct vbe_mode *mode_ptr.) 获.得 VBE模式信息 外贸
int set_vbe_mode (int mode_number). 设置VB.E模式 .
lin.ux_boot() 做一些危险的设置,然后跳转到Linxu安装的入.口代码 <性病>
multi_boot(int s.tart, int m.b_info) 这个函数启动一个核心使用多重启动的标 准方法 .
void con.sole_pu.tchar (int c) 通过这个函数在终端上显示字符 .
i.nt .console_getkey (void) 调用INT16从键盘上读取字符 .
int c.onsole_ch.eckkey (void) 检查是否某个键被一直按下去     外汇
int console_getxy (void) 调用INT10.获得光.标的位置 .
void console_gotoxy(int x,. int y) 调用IN.T10设置光标的位置 [成人用品]
vo.id console_cls (vo.id) 调用INT10 清空屏幕 教育
int console_setcursor (in.t on) 调用INT10设.置光标的类型 服务器
getrtsecs() 如果第二个值能被读取,则返回这个值.. (        游戏          )
currticks() 用Ticks为单位.返回当前时间.,一秒约为18-20个Ticks .
6.2 Commo.n.c 文件分析 .
在common.c文件中我找到了函数init_bios_info的实现的代码。分析发现,整个 init_bios_info文件主要是对 multi.boot_info这个结构进.行初.始化以及填充。 (        游戏          )
整个结构体分析如下:
str.uct multiboot_info <性病>
{
/* 多重启动信息的版本号.*/ .
unsigned long fla.gs; 学习
/* 可以使用的内存 */
unsigned long mem_lower;. --- 印刷
unsigned long mem_.upper;              电子
/* 主分区 */
unsigned l.ong boo.t_device; 服务器
/*核心的命令行*/
uns.igned long cmdline; .
/*启动模块的列表*/
unsigned long mod..s_count;              汽车
u.nsigned long mods_addr; .
union
{
struct
{
/* .(a.out) 核心标识表的信息 */ 外贸
unsigned long tabsize;. --- 印刷
u.nsigned long strsize; 教育
unsigned l.ong addr; .
uns.igned long pad; 教育
}
a;
struct
{
/* (ELF) 核.心标识表的信息*/ 教育
unsigne.d long num; .
unsigned long size;. .
unsigned long addr; ..
unsigned lon.g shndx;     健康
}
e;
}
syms;
/* 内存分布.图的缓存 */            鲜花
u.nsig.ned long mmap_length; 教育
unsigned .long mmap_addr;     外汇
/* 驱动器信息缓存 */
unsigned long. drives_len.gth; [成人用品]
unsigned long ..drives_addr; .
/* ROM 配置表 */
unsigne.d long config_.table; 域名
/* 启.动装载器的名称 */ 电脑
un.signed long boot_load.er_name;            女人
/* APM 表 */
unsigned long a.pm_table; 投资
/* 视频 */
unsigned lo.ng. vbe_control_info; 教育
unsigned long vbe_mod.e._info;           婚庆
unsigned sh.ort vbe_mode; .
unsigned short vbe_in.t.erface_seg; (广告)
un.signed short vbe_interface_.off; 电脑
unsigned short .vbe_interfac.e_len; 健康
};
通过调用asm.s中的底层功能模块,对这个结构进行初始化以后,直接调用.c.main函数。 健康
6.3 .Stage2.c 文件分析 学习
通过查找,在Stage2.c中找到了cmain函数,这个.应该就是Stage2这个小型操作系 统的入口了。然后程序就进入一个死循环,整个Stage2 就在这个死循环中运行。 接着调用reset()函数对stage2的内部变量进行初始化。通过open_preset_menu() 函数尝试打开已经设置好的菜单。如果用户没有设置.好菜单,那.么将返回0,如果 已经设置好了菜单则不返回0。如果.没有成功打开菜单,那么将通过grub_open()函 数尝试打开config_file。Grub使用内部的文件格式来打开.这样一个配置文件,如 果仍然打开失败,则跳出整个循环。如果打开成功,则根据打开的情况,即 is_preset变量的值的情况来判断是从预设菜单读入还是从配置文件读入命令。然 后通过把is_prese.t传入 get_line_from_c.onfig()函数,将命令读入cmline中。然 后通过find_command()函数查找有没有这条命令。.. 虚拟主机
在Grub中,保存命令的.格式是保存在一个builtin的结构体中的。这个结构体在 shared..h头文件中进行了定义。 (        游戏          )
s.truct builtin <性病>
{
/* 命令名称,重要,是搜索命令时的依据. */     外汇
char *name;
/* 命令函数,重要,是搜索匹配.后调用的函数. */ 学习
int (*fun.c) (ch.ar *, int); (广告)
/* 功能标识 */
int flags;
/* 简短帮助信息 */
char *sho.rt_doc;     外汇
/* 完整帮助信息 */
char *lon.g_doc; .
};
整个命令的表的定义如下
extern struc.t builtin *builtin_tabl.e[]; .
find_command()函数在cmdline..c中定义,它对整个builtin表进行遍历,然后比较 名称。如果在表中发现了这个命令,则返回指向当前buil.tin结构的指针。如果没 有发现这个命令则返回0同时返回一个.errnum。如果成功的找到了一条指令,然后 通过调用在cmdline.c中的skip_to ()函数,获得当前builtin指针所指向.结构的命 令的参数。然后通过(builtin->func) (arg, BUILTIN._MENU)直接调用此命令。最 后一直循环,直到没有命令可以取为.止。           婚庆
如果由于前面没有成功的打开预先配置的.文件而跳出循环,.则通过在cmdline.c文 件中定义的enter._cmdline()函数调用来启动命令行。在 enter_cmdline()函数 中,进入另一个循环等待接受命令。当通过get_cmdline()函数接收到命令以后, 仍然通过 find_command()函数调用来遍历builtin表,如果没有在.表中找到输入的 指令则返回一个errnum= ERR_UNRECONGNIZED。如果成功找到了这条指令,同样首 先调用在cmdline.c.中的skip_to ()函数,获得当前buil.tin指针所指向结构的命令 的参数。然后(builtin->func). (arg, BUILTIN._MENU)直接调用此命令。            女人
如果成功.的打开了菜单则跳.转到run_menu()函数,这里是grub中整个menu用户界.面 的主循环。首先有一个计时器grub_timout进行计时,如果grub_timeout root (hd0,a)
grub> kernel /boot/.lo.ader .
grub> boot
6.4.1  Root指令
调.用root指令的函数是在builtins.c中的r.oot_func (char *arg, int flags)函 .数。第一个参数指定了哪个磁盘驱动器,如hd0是.指第一块硬盘。第二个参数是分 区号。然后在root_func()中它有调用了 real_root_func (char *arg, int atte.mpt_mount)这个函数,并把参数arg传入real_.root_func中并把attempt_mount 设置为1。如果传入的arg是空的,那么就直接使用默认的驱动器。然后调用 set_device()函数,从字符串中提取出驱动器号和分区号。测试如果所填写的驱动 器号以及分区号读写没有问题,那么就在变.量saved_partition和.saved_drive中保 存读取的这两个数据。然后返回。 电脑
这个函数主要的作用是为GRUB指定一个根分区。.     健康
6.4.2  .Kernel指令     外汇
调用kernel指令的函数是在builti.ns.c文件中ke.rnel_func (char *arg, int flags)函数。在这个函数中,首先进入一个循环,对传进来的参数进行解析。如果 “--type=TYPE”参数被设置了,根据传入的参数设置. suggested_type变量赋予不用 的操作系统的值。当没有别的参数被设置以后,则.跳出循环。然后从参数中获得内 核的文件路径,赋值给 m.b_cmdline变量,然后通过load_image().函.数载入核心, 并且返回核心的类型。如果返回的核心类型是grub不支持得类型,即 kernel_type == KERNEL_TYPE_NONE返回1,成功则返回0。 --------------彩票
这个函数主要的作.用是,载入操作系统的核心。 .
6.4.3  Boot指令
调用boot指令的函数是在builtins.c文件中的boot_func(char *arg, int flags) 函数。如果被载.入的核心类型不是未知的,那么调用unset_int15_handler()函 数,清除int15 handler.。接着根据grub支持.的不同的操作系统调用相应的启动程序。.当启动的内核为BSD时调用bsd_boot ()函数,当启动的内核为LINUX时调用的函数时linux_.boot.()函数,当启动方式是链式.启动方式时,调用chain_stage1()函 数,当启动方式是多重启动时,调用multi_boot()函数。 (广告)
这个函数主要的作用.是.,根据不同的核心类型调用相应的启动函数。               乙肝
6.5 GRUB .Kernel分析总结 电影
通过分析,这个核心模块主要的工作是完成了GRUB这个微型操作系统的从磁盘到内 存的装载和运行。在asm.s这个文件中提供了从汇编代码到C代码转换的接口,也是 从这里开始正式载入了GRUB这个微型操作系统,可以说是GRUB运行的一个入口。同 时,在asm.s文件中,对底层的方法用汇.编语言进行了封装,方便在以后的C代码中. 调用。然后经过对BIOS进行一些初始化以后,正式进入了GRUB的主程序,即在 stage2中的cmain入口。从此这个微型的操作系统开始正式运行。然后值得注意的 是build.in这个.数据结构,这个结构就是GRUB所有.支持命令的数据结构。结构包括 了一个用来识别的名字.和一个用来调用.的方法。GRUB通过接收外部输入的指令的方 式,来间接的启动和装载其他的操.作系统。     健康
7 总结
7.1 .GRUB源代码分析总结 教育
通过对.整个源代码的分析,大致上整个GRUB启动到引导.其他操作系统分为如下几个 步骤。 [成人用品]
第一步 开机后,通过BIOS装载St.age1模块     健康
第二步 通.过Stage1模块装载Start模块 [成人用品]
第三步. 通过Start模块将整个.GRUB的内核载入内存 .
第四步 通过GRUB的一个S.hell的机制,作为一个小型的操作系统,来通过指令的方 式装载不.同的其他操作系统。 外贸
整个过程中GRUB启动的内存.映象.图如图7.1所示。 学习
总体分析下来,首先感觉到GRUB整个代码在编码方面是非常严谨的,特别是.整个程 序的构架体现出了它灵活容易扩展的特性。主要体现.在,它有别于普通的操作系统 引导程序,在BIOS启动时就直接去装载特定操作系统的模块或者内核,而是通过 BIOS的功能首先装载了.一个属于.自己的引导程序,也可以理解为 GRUB这个操作系 统的引导程序。也.就是说在引导任何用户的操作系统之前GRUB首先引导的是它的本 身。这样为将来的扩展性打下了非常好的基础。 .
由于GRUB采用了类似SHELL的方式来解释并运行用户设计好的脚本或者接受用.户输 入的指令,并且为用户提供了非常好.的底层的方法接口,所以用户可以非常灵活的 组合指令来引导不同的操作系统,同时并不要求用户对底层的物理结构有非常.高的 了解,只要能使用提供的指令就可以来操作配置多重启动的多个操作系统。并且, GRU.B提供了非常好的人.机交互界面,可以通过预先设置的指令,或者菜单来显示让 用户选择操作系统,相对来说就比较易用。 学习
同时GRUB也提供了非常好的扩展性,这个也是由于GRUB特殊的结构保.证的。首先 GRUB是一个开源的项目,它的源代码是向所有的用户和开发着公开的,这样无论是 用户的需求发生了变化,还是硬件的标准得到了提升,都能很快的在GRUB中得到实 现.。其次,GRUB的指令是非常容易添加的,用户只要了解了 G.RUB指令的格式,就 能非常容..易的在GRUB原始指令的基础上添加属于自己的指令,这样的设计相当程度 上提高了程序的模块化,耦合度比较低。 <性病>


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/84810/showart_1421486.html           女人
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
快速回复
限100 字节
如果您在写长篇帖子又不马上发表,建议存为草稿
 
上一个 下一个