无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
查看: 8576|回复: 12
打印 上一主题 下一主题

[转贴] GRUB启动代码详解

  [复制链接]
跳转到指定楼层
1#
发表于 2016-1-24 14:11:54 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 有阴也有阳 于 2016-1-24 18:31 编辑

                                                                                  GRUB2的介绍

         目前Grub1已经停止开发了,不再增加新的功能,所有的开发都转移到Grub2上了,Grub 2 是新一代的Grub,它实现了一些Grub中所没有的功能:

1.模块化设计   
不同于Grub的单一内核结构,Grub 2 的功能分布在很多的小模块中,并且能在运行时动态装载和卸除。
  
2.支持多体系结构   Grub 2可支持PC(i386), MAC(powerpc)等不同的体系结构,而且支持最新的EFI架构。
  
3.国际化的支持   Grub 2 可以支持非英语的语言。
  
4.内存管理   Grub 2 有真正的内存管理系统。
  
5.脚本语言   Grub 2 可以支持脚本语言,例如条件,循环,变量,函数等。   
当然,Grub 2正处在开发阶段,因此以上的某些功能可能现阶段还不是很完善。
如果你熟悉Grub2,应该可以看明白里面的内容。要注意的是:   
a、timeout, default等参数用变量来储存   
b、菜单项由menuentry定义   
c、第1个分区是(hd0,1)而不是(hd0,0)
        理论的东西说多了大家估计也晕,举个简单的例子:在grub1中,要改变启动背景的时候只能选择支持640X480分辨率并且格式也只能是.xpm的图片,分辨率稍微大点的图就显示不出来了,但grub2不存在这个问题,它有更绚丽的菜单界面,grub2默认.png  .tga  .jpeg等很多种格式的图片都支持,而且支持的图片分辨率也更大。


GRUB2启动代码分析
                                 
#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by /usr/sbin/grub-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#
### BEGIN /etc/grub.d/00_header ###
if [ -s $prefix/grubenv ]; then
#如果“$prefix/grubenv”目录不为空

  load_env
#从grubenv文件中加载环境变量
fi
set default="0"  
#启动第1项#

if [ ${prev_saved_entry} ]; then #如果prev_saved_entry的值不为空
  set saved_entry=${prev_saved_entry}  #将saved_entry的值设置成变量prev_saved_entry的值。

  save_env saved_entry #将变量saved_entry保存到grubenv文件中。

  set prev_saved_entry= #将prev_saved_entry的值设置为空

  save_env prev_saved_entry #将prev_saved_entry保存到grubenv文件中

  set boot_once=true #将boot_once的值设置为真(貌似是为了标志已经设置过启动的相关环境变量了)

fi
function savedefault {
  if [ -z ${boot_once} ]; then #如果已经设置过相关环境变量

saved_entry=${chosen} #用变量chosen的值给saved_entry赋值。

save_env saved_entry
#将saved_entry保存到grubenv文件中
  fi
}
function recordfail {   #存在启动失败记录时调用,设置变量recordfail。
  set recordfail=1
  if [ -n ${have_grubenv} ]; then if [ -z ${boot_once} ]; then save_env recordfail; fi; fi #如果grubenv文件存在,并已设置过相关变量,就将变量recordfail保存到grubenv文件。
}
insmod ext2        
#插入ext2文件系统支持的模块

set root='(hd0,9)'   
# 指定系统root分区,也就是 / 分区为第1个磁盘的第9个分区

search --no-floppy --fs-uuid --set d9985e84-7b54-4e5d-8ce9-c25cf88330aa #  指定uuid= d9985e84-7b54-4e5d-8ce9-c25cf88330aa的分区为root分区,如果前面的分区 #  号(hd0,9)的uuid与这里的uuid一致,这两句作用一样,如果不一致,则指定uuid的起 #  作用。

if loadfont /usr/share/grub/unicode.pf2 ; then #设置终端字体,unicode.pf2支持中文字符显示

  set gfxmode=640x480 #设置显示分辨率,默认为640×480

  insmod gfxterm #插入终端模块gfxterm,支持中文字符显示和支持24位图像。

  insmod vbe #插入vbe模块,GRUB2引入模块化机制,要使用它,需要在这里加入。

  if terminal_output gfxterm ; then true ; else
#检测grub2是否将终端设设定为gfxterm

    # For backward compatibility with versions of terminal.mod that don't
    # understand terminal_output
terminal gfxterm         
#设定grub2终端为gfxterm

  fi
fi
insmod ext2  
#插入ext2文件系统支持的模块  
set root='(hd0,9)'   
# 指定系统root分区,也就是 / 分区为第1个磁盘的第9个分区
search --no-floppy --fs-uuid --set d9985e84-7b54-4e5d-8ce9-c25cf88330aa #  指定uuid= d9985e84-7b54-4e5d-8ce9-c25cf88330aa的分区为root分区,如果前面的分区 #  号(hd0,9)的uuid与这里的uuid一致,这两句作用一样,如果不一致,则指定uuid的起 #  作用。

set locale_dir=($root)/boot/grub/locale
set lang=zh
insmod gettext
if [ ${recordfail} = 1 ]; then
  set timeout=-1    #若有启动失败的记录,则不再倒计时。
else
  set timeout=10   #如果停留在grub选择系统界面,停顿时间就设置成10秒,十秒后按默认启动项
#启动。
fi
### END /etc/grub.d/00_header ###
### BEGIN /etc/grub.d/05_debian_theme
###设置菜单颜色和背景颜色

set menu_color_normal=white/black   
#设定菜单字体及背景颜色

set menu_color_highlight=black/light-gray #设定选择项字体及背景颜色

### END /etc/grub.d/05_debian_theme ###
### BEGIN /etc/grub.d/10_linux ###
#10_linux为系统自动添加的当前root分区linux引导项


#菜单项,要包括 menuentry 双引号" " 和大括号 { }才完整,否则不显示菜单
menuentry ''Ubuntu,Linux 2.6.32-30-generic'' --class ubuntu --class gnu-linux --class gnu --class os {
        recordfail
#执行recordfail 函数
        insmod ext2
#插入ext2文件系统支持的模块
        set root='(hd0,9)'  
#指定系统root分区,也就是 / 分区为第1个磁盘的第9个分区

        search --no-floppy --fs-uuid --set d9985e84-7b54-4e5d-8ce9-c25cf88330aa #这句与set root=(hd0,9)效果一样,可删除其一,二者不一致以这句为准

        linux        /boot/vmlinuz-2.6.32-30-generic root=UUID=d9985e84-7b54-4e5d-8ce9-c25cf88330aa ro   quiet splash #加载内核
# ro:可读写,当启动分区是JFS等格式时需要使用此参数使得系统可以在启动是存放日志。
#quiet:安静模式,不显示启动详细信息。
#splash:显示徽标。

        initrd        /boot/initrd.img-2.6.32-30-generic #初始RAM磁盘,在系统引导过程中挂载的一个临时根文件系统。

}
menuentry ''Ubuntu,Linux 2.6.32-30-generic (恢复模式)'' --class ubuntu --class gnu-linux --class gnu --class os { #linux的恢复模式,与linux的启动项基本一样。

        recordfail #执行recordfail 函数

        insmod ext2
        set root='(hd0,9)'
        search --no-floppy --fs-uuid --set d9985e84-7b54-4e5d-8ce9-c25cf88330aa
        echo        '载入 Linux ...'
        linux        /boot/vmlinuz-2.6.32-30-generic root=UUID=d9985e84-7b54-4e5d-8ce9-c25cf88330aa ro single  #加载内核 貌似这个single参数就是指定的修复模式

        echo        '载入引导虚拟磁盘。'
        initrd        /boot/initrd.img-2.6.32-30-generic #初始RAM磁盘,在系统引导过程中挂载的一个临时根文件系统。

}
### END /etc/grub.d/10_linux ###

#20_memtest86+为系统自动添加的内存测试菜单项
menuentry "Memory test (memtest86+)" {
        insmod ext2
        set root='(hd0,9)'
        search --no-floppy --fs-uuid --set=root f8656ad4-390d-4a72-832a-1f4b313ac793
        linux16        /boot/memtest86+.bin
}
menuentry "Memory test (memtest86+, serial console 115200)" {
        insmod ext2
        set root='(hd0,9)'
        search --no-floppy --fs-uuid --set=root f8656ad4-390d-4a72-832a-1f4b313ac793
        linux16        /boot/memtest86+.bin console=ttyS0,115200n8
}
### END /etc/grub.d/20_memtest86+ ###


### BEGIN /etc/grub.d/30_os-prober ### #  30_os-prober或30_others为系统自动查找并添加其他系统菜单项,按windows、
#  linux、macos顺序查找并添加,支持windows 7识别。
if [ "x${timeout}" != "x-1" ]; then
  if keystatus; then
    if keystatus --shift; then
      set timeout=-1
    else
      set timeout=10
    fi
  else
    if sleep --interruptible 3 ; then
      set timeout=10
    fi
  fi
fi   
##直接启动默认的系统,需要选择引导不同的系统时才按几下shift键进入grub选择系统界面。##



menuentry "Windows 7 (loader) (on /dev/sda1)" {

        insmod ntfs
#插入NTFS文件系统支持的模块
        set root='(hd0,1)'
#指定系统root分区,也就是 / 分区为第1个磁盘的第1个分区

        search --no-floppy --fs-uuid --set 5802c4e402c4c7e8 #这句与set root=(hd0,1)效果一样,可删除其一,二者不一致以这句为准。

        chainloader +1
#指示GRUB读入分区的第一个扇区的引导记录。

}
### END /etc/grub.d/30_os-prober ###

### BEGIN /etc/grub.d/40_custom ###
#40_custom为自定义的启动项,如启动cdlinux

# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
### END /etc/grub.d/40_custom ###
### BEGIN /etc/grub.d/41_custom ###
if [ -f  $prefix/custom.cfg ]; then  
##如果$prefix/custom.cfg满足正规文件##
  source $prefix/custom.cfg;  ##重新加载此变量##
fi
### END /etc/grub.d/41_custom ###
2#
发表于 2016-1-25 08:57:04 | 只看该作者
学习一下,谢谢分享
回复

使用道具 举报

3#
发表于 2016-1-25 10:40:01 | 只看该作者
学习了,想问一下楼主有没有方法解决u盘版的grub2读取大文件的winpe时间超慢的问题?比如600M左右的pe,用grub2直接加载读取时间大约3到4分钟,太久了,我分析原因1,U盘本来的读取速度有限,2,grub2加载ISO文件机制是不是有问题(猜想理由是我用grub4dos快的多)。有没有方法加快读取时间?我参考各位前辈写的菜单:
menuentry 'win10pe'{
    set root='(hd0,msdos1)'
    linux16 /memdisk iso raw
    initrd16 /Win10.iso
}

点评

在BIOS启动部分我的用法是直接使用grub4dos,或者由grub2直接转grub4dos,等待时间为0......  详情 回复 发表于 2016-1-25 12:24
回复

使用道具 举报

4#
 楼主| 发表于 2016-1-25 12:24:43 | 只看该作者
liy 发表于 2016-1-25 10:40
学习了,想问一下楼主有没有方法解决u盘版的grub2读取大文件的winpe时间超慢的问题?比如600M左右的pe,用g ...

在BIOS启动部分我的用法是直接使用grub4dos,或者由grub2直接转grub4dos,等待时间为0......
回复

使用道具 举报

5#
发表于 2016-2-20 14:01:57 | 只看该作者

新学习grub2,请教下  fi 是什么语句?

点评

end if的意思  详情 回复 发表于 2016-2-23 22:06
回复

使用道具 举报

6#
发表于 2016-2-23 22:06:09 | 只看该作者
sskgaiqny 发表于 2016-2-20 14:01
新学习grub2,请教下  fi 是什么语句?

end if的意思

点评

谢谢,原来如此  详情 回复 发表于 2016-2-24 13:05
回复

使用道具 举报

7#
发表于 2016-2-24 13:05:47 | 只看该作者

谢谢,原来如此
回复

使用道具 举报

8#
发表于 2018-8-20 11:00:46 | 只看该作者
学习一下
回复

使用道具 举报

9#
发表于 2018-8-22 11:33:19 | 只看该作者
有介绍源码的就好了
回复

使用道具 举报

10#
发表于 2018-8-22 13:49:00 | 只看该作者
wintoflash 发表于 2018-8-22 12:24
如果你想查找GRUB2源码的相关问题,那我只能说你找错论坛了,论坛里还真没有研究过GRUB2源码的人。
你应 ...

只是最近遇到的grub2问题:grub没有加载usb keyboard相关的module(例如xhci ehci等),但是可以使用usb keyboard,这个原因还没有确认
回复

使用道具 举报

11#
发表于 2018-8-22 15:44:03 | 只看该作者
wintoflash 发表于 2018-8-22 13:55
原来这个问题是你问的啊。。
https://lists.gnu.org/archive/html/grub-devel/2018-08/msg00069.html

是的,目前在grub spec上看到了这么一句话:
If the operating system or boot loader that runs
after GRUB uses its own keyboard driver rather than the BIOS keyboard functions
then sendkey will have no effect.
回复

使用道具 举报

12#
发表于 2018-9-11 17:23:22 | 只看该作者
学习
回复

使用道具 举报

13#
发表于 2019-9-25 15:36:48 | 只看该作者
谢谢分享,学习中
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2024-11-27 05:48

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表