參考資料##
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_GFXMODE
和 GRUB_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 的正確打開姿勢。