在 21 世紀該怎樣編譯 Linux 核心

Seth Kenlon發表於2019-10-06

也許你並不需要編譯 Linux 核心,但你能透過這篇教程快速上手。

在 21 世紀該怎樣編譯 Linux 核心

在計算機世界裡,核心kernel是處理硬體與一般系統之間通訊的低階軟體low-level software。除過一些燒錄進計算機主機板的初始韌體,當你啟動計算機時,核心讓系統意識到它有一個硬碟驅動器、螢幕、鍵盤以及網路卡。分配給每個部件相等時間(或多或少)使得影像、音訊、檔案系統和網路可以流暢甚至並行地執行。

然而,對於硬體的需求是源源不斷的,隨著釋出的硬體越多,核心就必須納入更多程式碼來保證那些硬體正常工作。得到具體的數字很困難,但是 Linux 核心無疑是硬體相容性方面的頂級核心之一。Linux 操作著無數的計算機和行動電話、工業用途和愛好者使用的板級嵌入式系統(SoC)、RAID 卡、縫紉機等等。

回到 20 世紀(甚至是 21 世紀初期),對於 Linux 使用者來說,在剛買到新的硬體後就需要下載最新的核心程式碼並編譯安裝才能使用這是不可理喻的。而現在你也很難見到 Linux 使用者為了好玩而編譯核心或透過高度專業化定製的硬體的方式賺錢。現在,通常已經不需要再編譯 Linux 核心了。

這裡列出了一些原因以及快速編譯核心的教程。

更新當前的核心

無論你買了配備新顯示卡或 Wifi 晶片集的新品牌電腦還是給家裡配備一個新的印表機,你的作業系統(稱為 GNU+Linux 或 Linux,它也是該核心的名字)需要一個驅動程式來開啟新部件(顯示卡、晶片集、印表機和其他任何東西)的通道。有時候當你插入某些新的裝置時而你的電腦表示發現了它,這具有一定的欺騙性。別被騙到了,有時候那就夠了,但更多的情況是你的作業系統僅僅是使用了通用的協議檢測到安裝了新的裝置。

例如,你的計算機也許能夠鑑別出新的網路印表機,但有時候那僅僅是因為印表機的網路卡被設計成為了獲得 DHCP 地址而在網路上標識自己。它並不意味著你的計算機知道如何傳送文件給印表機進行列印。事實上,你可以認為計算機甚至不“知道”那臺裝置是一個印表機。它也許僅僅是顯示網路有個裝置在一個特定的地址上,並且該裝置以一系列字元 “p-r-i-n-t-e-r” 標識自己而已。人類語言的便利性對於計算機毫無意義。計算機需要的是一個驅動程式。

核心開發者、硬體製造商、技術支援和愛好者都知道新的硬體會不斷地釋出。它們大多數都會貢獻驅動程式,直接提交給核心開發團隊以包含在 Linux 中。例如,英偉達顯示卡驅動程式通常都會寫入 Nouveau 核心模組中,並且因為英偉達顯示卡很常用,它的程式碼都包含在任一個日常使用的發行版核心中(例如當下載 FedoraUbuntu 得到的核心)。英偉達也有不常用的地方,例如嵌入式系統中 Nouveau 模組通常被移除。對其他裝置來說也有類似的模組:印表機得益於 FoomaticCUPS,無線網路卡有 b43、ath9k、wl 模組等等。

發行版往往會在它們 Linux 核心的構建中包含儘可能多合理的驅動程式,因為他們想讓你在接入新裝置時不用安裝驅動程式能夠立即使用。對於大多數情況來說就是這樣的,尤其是現在很多裝置廠商都在資助自己售賣硬體的 Linux 驅動程式開發,並且直接將這些驅動程式提交給核心團隊以用在通常的發行版上。

有時候,或許你正在執行六個月之前安裝的核心,並配備了上週剛剛上市令人興奮的新裝置。在這種情況下,你的核心也許沒有那款裝置的驅動程式。好訊息是經常會出現那款裝置的驅動程式已經存在於最近版本的核心中,意味著你只要更新執行的核心就可以了。

通常,這些都是透過安裝包管理軟體完成的。例如在 RHEL、CentOS 和 Fedora 上:

$ sudo dnf update kernel

在 Debian 和 Ubuntu 上,首先獲取你當前核心的版本:

$ uname -r
4.4.186

搜尋新的版本:

$ sudo apt update
$ sudo apt search linux-image

安裝找到的最新版本。在這個例子中,最新的版本是 5.2.4:

$ sudo apt install linux-image-5.2.4

核心更新後,你必須 reboot (除非你使用 kpatch 或 kgraft)。這時,如果你需要的裝置驅動程式包含在最新的核心中,你的硬體就會正常工作。

安裝核心模組

有時候一個發行版沒有預計到使用者會使用某個裝置(或者該裝置的驅動程式至少不足以包含在 Linux 核心中)。Linux 對於驅動程式採用模組化方式,因此儘管驅動程式沒有編譯進核心,但發行版可以推送單獨的驅動程式包讓核心去載入。儘管有些複雜但是非常有用,尤其是當驅動程式沒有包含進核心中而是在引導過程中載入,或是核心中的驅動程式相比模組化的驅動程式過期時。第一個問題可以用 “initrd” 解決(初始化 RAM 磁碟),這一點超出了本文的討論範圍,第二點透過 “kmod” 系統解決。

kmod 系統保證了當核心更新後,所有與之安裝的模組化驅動程式也得到更新。如果你手動安裝一個驅動程式,你就體驗不到 kmod 提供的自動化,因此只要能用 kmod 安裝包,就應該選擇它。例如,儘管英偉達驅動程式以 Nouveau 模組構建在核心中,但官方的驅動程式僅由英偉達釋出。你可以去網站上手動安裝英偉達旗下的驅動程式,下載 “.run” 檔案,並執行提供的 shell 指令碼,但在安裝了新的核心之後你必須重複相同的過程,因為沒有任何東西告訴包管理軟體你手動安裝了一個核心驅動程式。英偉達驅動著你的顯示卡,手動更新英偉達驅動程式通常意味著你需要透過終端來執行更新,因為沒有顯示卡驅動程式將無法顯示。

Nvidia configuration application

然而,如果你透過 kmod 包安裝英偉達驅動程式,更新你的核心也會更新你的英偉達驅動程式。在 Fedora 和相關的發行版中:

$ sudo dnf install kmod-nvidia

在 Debian 和相關發行版上:

$ sudo apt update
$ sudo apt install nvidia-kernel-common nvidia-kernel-dkms nvidia-glx nvidia-xconfig nvidia-settings nvidia-vdpau-driver vdpau-va-driver

這僅僅是一個例子,但是如果你真的要安裝英偉達驅動程式,你也必須遮蔽掉 Nouveau 驅動程式。參考你使用發行版的文件獲取最佳的步驟吧。

下載並安裝驅動程式

不是所有的東西都包含在核心中,也不是所有的東西都可以作為核心模組使用。在某些情況下,你需要下載一個由供應商編寫並繫結好的特殊驅動程式,還有一些情況,你有驅動程式,但是沒有配置驅動程式的前端介面。

有兩個常見的例子是 HP 印表機和 Wacom 數位板。如果你有一臺 HP 印表機,你可能有能夠和印表機通訊的通用的驅動程式,甚至能夠列印出東西。但是通用的驅動程式卻不能為特定型號的印表機提供定製化的選項,例如雙面列印、校對、紙盒選擇等等。HPLIP(HP Linux 成像和列印系統)提供了選項來進行任務管理、調整列印設定、選擇可用的紙盒等等。

HPLIP 通常包含在包管理軟體中;只要搜尋“hplip”就行了。

HPLIP in action

同樣的,電子藝術家主要使用的數位板 Wacom 的驅動程式通常也包含在核心中,但是例如調整壓感和按鍵功能等設定只能透過預設包含在 GNOME 的圖形控制皮膚訪問。但也可以作為 KDE 上額外的程式包“kde-config-tablet”來訪問。

這裡也有幾個類似的個別例子,例如核心中沒有驅動程式,但是以 RPM 或 DEB 檔案提供了可供下載並且透過包管理軟體安裝的 kmod 版本的驅動程式。

打上補丁並編譯你的核心

即使在 21 世紀的未來主義烏托邦裡,仍有廠商不夠了解開源,沒有提供可安裝的驅動程式。有時候,一些公司為驅動程式提供開原始碼,而需要你下載程式碼、修補核心、編譯並手動安裝。

這種釋出方式和在 kmod 系統之外安裝打包的驅動程式擁有同樣的缺點:對核心的更新會破壞驅動程式,因為每次更換新的核心時都必須手動將其重新整合到核心中。

令人高興的是,這種事情變得少見了,因為 Linux 核心團隊在呼籲公司們與他們交流方面做得很好,並且公司們最終接受了開源不會很快消失的事實。但仍有新奇的或高度專業的裝置僅提供了核心補丁。

官方上,對於你如何編譯核心以使包管理器參與到升級系統如此重要的部分中,發行版有特定的習慣。這裡有太多的包管理器,所以無法一一涵蓋。舉一個例子,當你使用 Fedora 上的工具例如 rpmdevbuild-essential,Debian 上的 devscripts

首先,像通常那樣,找到你正在執行核心的版本:

$ uname -r

在大多數情況下,如果你還沒有升級過核心那麼可以試試升級一下核心。搞定之後,也許你的問題就會在最新發布的核心中解決。如果你嘗試後發現不起作用,那麼你應該下載正在執行核心的原始碼。大多數發行版提供了特定的命令來完成這件事,但是手動操作的話,可以在 kernel.org 上找到它的原始碼。

你必須下載核心所需的任何補丁。有時候,這些補丁對應具體的核心版本,因此請謹慎選擇。

通常,或至少在人們習慣於編譯核心的那時,都是拿到原始碼並對 /usr/src/linux 打上補丁。

解壓核心原始碼並打上需要的補丁:

$ cd /usr/src/linux
$ bzip2 --decompress linux-5.2.4.tar.bz2
$ cd  linux-5.2.4
$ bzip2 -d ../patch*bz2

補丁檔案也許包含如何使用的教程,但通常它們都設計成在核心原始碼樹的頂層可用來執行。

$ patch -p1 < patch*example.patch

當核心程式碼打上補丁後,你可以繼續使用舊的配置來對打了補丁的核心進行配置。

$ make oldconfig

make oldconfig 命令有兩個作用:它繼承了當前的核心配置,並且允許你配置補丁帶來的新的選項。

你或許需要執行 make menuconfig 命令,它啟動了一個基於 ncurses 的選單介面,列出了新的核心所有可能的選項。整個選單可能看不過來,但是它是以舊的核心配置為基礎的,你可以遍歷選單並且停用掉你沒有或不需要的硬體模組。另外,如果你知道自己有一些硬體沒有包含在當前的配置中,你可以選擇構建它,當作模組或者直接嵌入核心中。理論上,這些並不是必要的,因為你可以猜想,當前的核心執行良好只是缺少了補丁,當使用補丁的時候可能已經啟用了所有裝置所必要的選項。

下一步,編譯核心和它的模組:

$ make bzImage
$ make modules

這會產生一個叫作 vmlinuz 的檔案,它是你的可引導核心的壓縮版本。儲存舊的版本並在 /boot 資料夾下替換為新的。

$ sudo mv /boot/vmlinuz /boot/vmlinuz.nopatch
$ sudo cat arch/x86_64/boot/bzImage > /boot/vmlinuz
$ sudo mv /boot/System.map /boot/System.map.stock
$ sudo cp System.map /boot/System.map

到目前為止,你已經打上了補丁並且編譯了核心和它的模組,你安裝了核心,但你並沒有安裝任何模組。那就是最後的步驟:

$ sudo make modules_install

新的核心已經就位,並且它的模組也已經安裝。

最後一步是更新你的載入程式,為了讓你的計算機在載入 Linux 核心之前知道它的位置。GRUB 載入程式使這一過程變得相當簡單:

$ sudo grub2-mkconfig

現實生活中的編譯

當然,現在沒有人手動執行這些命令。相反的,參考你的發行版,尋找發行版維護人員使用的開發者工具集修改核心的說明。這些工具集可能會建立一個整合所有補丁的可安裝軟體包,告訴你的包管理器來升級並更新你的載入程式。

核心

作業系統和核心都是玄學,但要理解構成它們的元件並不難。下一次你看到某個技術無法應用在 Linux 上時,深呼吸,調查可用的驅動程式,尋找一條捷徑。Linux 比以前簡單多了——包括核心。


via: https://opensource.com/article/19/8/linux-kernel-21st-century

作者:Seth Kenlon 選題:lujun9972 譯者:LuMing 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出

相關文章