10.06 在 21 世紀該怎樣編譯 Linux 內核

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

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

-- Seth Kenlon(作者)

在計算機世界裡, 內核(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 內核模塊中,並且因為英偉達顯卡很常用,它的代碼都包含在任一個日常使用的發行版內核中(例如當下載 Fedora 或 Ubuntu 得到的內核)。英偉達也有不常用的地方,例如嵌入式系統中 Nouveau 模塊通常被移除。對其他設備來說也有類似的模塊:打印機得益於 Foomatic 和 CUPS ,無線網卡有 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 腳本,但在安裝了新的內核之後你必須重複相同的過程,因為沒有任何東西告訴包管理軟件你手動安裝了一個內核驅動程序。英偉達驅動著你的顯卡,手動更新英偉達驅動程序通常意味著你需要通過終端來執行更新,因為沒有顯卡驅動程序將無法顯示。


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

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”就行了。


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

HPLIP in action


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

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

打上補丁並編譯你的內核

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

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

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

官方上,對於你如何編譯內核以使包管理器參與到升級系統如此重要的部分中,發行版有特定的習慣。這裡有太多的包管理器,所以無法一一涵蓋。舉一個例子,當你使用 Fedora 上的工具例如 rpmdev 或 build-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中國 榮譽推出


分享到:


相關文章: