京山游侠

专注技术 拒绝扯淡
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

逆天的 GRUB

Posted on 2015-05-31 16:00  京山游侠  阅读(4527)  评论(0编辑  收藏  举报

参考资料##

GRUB 的文档在这里:https://www.gnu.org/software/grub/manual/grub/

Linux 的启动过程和 GRUB 的地位##

Linux 系统启动的过程是这样的:先由 BIOS 启动一个系统引导程序;然后系统引导程序负责把 Linux 的内核加载到内存,同时把 initrd 加载到内存,然后把控制权交给 Linux 的内核;Linux 的内核初始化完成后,将控制权交给 init 程序;init 程序负责启动各种服务。如果要启动图形桌面系统,则 init 先启动一个窗口管理器,由窗口管理器负责用户的登录和验证;用户登录和验证成功后,窗口管理器负责启动 X 服务器和客户端,进入桌面系统。如果是不需要图形桌面系统的 Linux,则 init 启动 login 程序,login 程序负责用户的登录和验证,验证成功后,启动一个 shell。

GRUB 就是目前 Linux 系统使用的系统引导程序,是计算机启动后运行的第一个程序(当然,BIOS除外)。它在将 Linux 内核加载到内存的时候,还可以向内核传递各种参数。目前的 Linux 发行版使用的 GRUB 都已经是第 2 版了,它的功能和配置都和以前的版本不一样。网上很多文章都是基于以前的 GRUB Legacy 版本进行的讲解,已经不能适应现在新的形势了,所以才有了我的这篇文章。

从上面的介绍可以看出,GRUB 是计算机启动后运行的第一个程序,这个时候 Linux 的内核还没有加载,其它的程序也都不可能运行。这时有人就会想了,这个 GRUB 的功能应该相当有限吧。我刚开始也是这么想的。但是当我读完上面参考资料中给出的 GRUB 文档后,我的思想被彻底颠覆了。GRUB 的功能太 TM 强了,所以我才把这篇文章取名“逆天的 GRUB”。

GRUB 功能概览##

那么这个一开机就启动的简单程序究竟具有哪些让人意想不到的功能呢?请看我列举几条:

  • 能够访问任何设备上的数据,不管你是硬盘、软盘还是光盘;
  • 能够探测到所有的内存;
  • 能够识别大部分的文件系统,不管你是 FAT32、NTFS 还是 ext2/ext3/ext4;
  • 能够识别文件系统中的文件,文档中说它可识别大部分可执行文件格式,ELF什么的根本不在话下;
  • 能够使用 .png、.jpg 格式的图片作为背景,说明它能够识别一些图片格式;
  • 对字体的支持稍微差一点,好像只能使用 PFF2 格式的字体;
  • 当然可以读取和输出硬盘上的文本文件;
  • 据说还能播放乐曲;
  • 支持联网,可以从网络上启动操作系统;
  • 可以支持串口输入输出。

这些功能真的是已经超强了,就快赶上一个操作系统了。重要的是,它还提供了一个非常好用的命令行界面,该命令行界面的使用方法和 Linux 系统中的 Shell 及其接近,也支持编程、支持环境变量,其编程的语法也和 Bash 差不多。再加上 GRUB 提供的丰富的命令,该界面使用起来爽得不要不要的。

GRUB实战##

实践出真知,下面以 Ubuntu 为例开始实战。

GRUB的界面###

刚安装好的 Ubuntu 启动时不显示 GRUB 界面,因为它在设置中把它隐藏了。它的启动画面是这样的:

必须按一下 ESC 键,我们才能够看到 GRUB 的菜单,它是这样的:

上面这个界面想必大家已经很熟悉了。在这个界面中,如果按下 c 键,就会切换到 GRUB 的命令行界面,如下:

还有一种情况就是,如果大家在使用 Linux 过程中不小心删除了 /boot/grub/grub.cfg,或者配置错误,或者删除了 Linux 系统所在的硬盘分区的数据,使得 GRUB 无法正确加载 Linux 系统,也会自动进入到这个命令行界面。

GRUB 支持的命令###

GRUB 的命令补全功能非常方便,只要按一下 TAB 键,就可以显示它支持的所有命令。命令之后按 TAB 键,可以自动补全文件名。下面是 GRUB 支持的命令,我按 TAB 键调出来的:

使用 ls 命令可以列出目录和文件,使用cat命令可以输出文本文件的内容。在 GRUB 中,使用 (hd0, msdos1) 或者 (hd0, gpt1) 识别硬盘分区,使用 (hd0, gptN)/boot/grub/grub.cfg这样的形式识别文件。由于 GRUB 能自动识别根分区,所以我下面的命令中省略掉了指定硬盘分区的部分。如下图:

在上图中,我使用 cat /etc/fstab 命令显示了我系统中硬盘分区的情况。可以看到,我使用的是 GPT 分区格式和 EFI 固件,硬盘分了三个去,第一个分区的挂载点是 /boot/efi,并且是 vfat 格式的文件系统,第二个分区的挂载点是根目录 /,第三个分区是 swap 空间。按照 GRUB 的术语,则分区(hd0, gpt1)是挂载的/boot/efi,分区(hd0, gpt2)是根目录,分区(hd0, gpt3)是交换分区。可以看到,GRUB 中硬盘是从 0 开始计数的,而分区是从 1 开始计数的。

GRUB 的环境变量###

我在之前的某一篇随笔中讲过,命令行参数、环境变量、配置文件是对软件进行配置的三驾马车,GRUB 也不例外,它的很多行为也受环境变量控制。下面看一个例子,当我想查看 GRUB 的启动配置文件/boot/grub/grub.cfg时,使用cat命令查看该文件的内容,但是由于该文件太长,一个屏幕显示不完,所以只能看到最后几行,如下两图:

这是非常蛋疼的,但还不是最郁闷的,毕竟/boot/grub/grub.cfg是系统中的一个文件,大不了我进 Linux 后用 vim 看。最蛋疼的是某些命令的输出,只能看到最后几行,又不能保存下来,真的让人捉急。就像下面这个例子,我使用 videoinfo 命令查看我的 GRUB 支持哪些图形分辨率:

这个时候,就只能通过设置环境变量的方法来解决问题了。使用set pager=1命令设置环境变量pager,让 GRUB 的输出启用分页,如下图:

我们还可以通过不带参数的set命令显示所有可用的环境变量,如下图:

也可以使用echo命令输入某一个环境变量,如下图:

更改分辨率###

我们可以控制 GRUB 显示界面的分辨率,还可以通过 GRUB 控制 Linux 启动进入字符模式后的分辨率。前提条件是要看我们的 BIOS 和显卡支持哪些模式。可以通过 videoinfo 命令查看,如下图:

我使用的是虚拟机,因为玩 GRUB 不使用虚拟机无法截图啊。如果采取的是 EFI 固件,则其输出如下:

如果采取的是 Legacy BIOS,则其输出如下:

可以看到,如果使用的是 Legacy BIOS,它的显示模式是由 ' VESA BIOS Extension Video Driver ' 提供支持的。如果使用的是 EFI,则其显示模式是由 ' EFI GOP driver ' 提供支持的。在我的虚拟机中,它们能提供的最高分辨率也只有 1152 x 864,远远达不到 1920 x 1080。但是在我的物理机中,都是可以达到 1920 x 1080。而且貌似只能进入 1920 x 1080,想改小还改不了。在物理机上,想通过改小分辨率,然后利用显示器的放大功能来放大字体的梦想是破灭了的。

在虚拟机中,我要做的是把分辨率改大,至少让我完全进入 Linux 字符界面的时候有个 1024 x 768 的分辨率吧,不然字符界面用起来岂不是太憋屈。可以通过修改 /etc/default/grub文件,然后调用sudo update-grub命令更新 GRUB。如下图,使用sudo vim /etc/default/grub修改配置文件:

在上面的这个文件中的注释里,也写得很明白了,要修改 GRUB 和 Linux 字符界面的分辨率,可以通过修改 GRUB_GFXMODEGRUB_GFXPAYLOAD_LINUX 参数来设置,而且千万不要设置GRUB_TERMINAL=console,不然就真的进入只有文字的文字模式了,没有 Graphic 的支持,还谈啥分辨率呢。

然后重启系统,可以看到我们的 GRUB 界面变大了一圈,如下两图:

下面进入 Linux 的字符界面,进入 Linux 字符界面的方式是启动进入 Linux 后,使用 sudo systemctl set-default multi-user.target,然后重启,在 1024 x 768 的分辨率下开一个 vim 看看,如下图:

又找到了怀旧的感觉,不是吗?唯一的缺憾是字太小。如果是在我的物理机上,15.6寸 1920 x 1080 的屏幕,字会小得根本无法看。下一篇,我们再来探讨 Framebuffer 的正确打开姿势。