爲Deepin Linux編譯內核

Deepin Linux是Linux中的新銳力量,獨創的桌面環境、應用生態與設計時的種種匠心,使得它擁有非常酷炫的體驗,成爲越來越多電腦愛好者的首選。

不過,基於Linux的操作系統,並不像Windows一樣能完美解決驅動問題。在Windows中,只需找到對應的官方驅動安裝即可;但是Linux卻是將設備驅動程序都集成在內核中,以及作爲內核模塊加載,這一切都是在編譯內核時就已一錘定音。如此機制,使得Deepin發行版的一套編譯好的內核並不能完美適用於所有設備。

筆者就在Linux的驅動上吃了苦頭。面前這臺備用筆記本是ThinkPad X200,X系列的老旗艦,在運行Deepin的時候,顯卡驅動就出現了問題,表現爲每次關蓋後重新打開,或者是待機後重新喚醒,移動鼠標就會在鼠標指針下方區域出現畫面撕裂、閃屏的情況,即便使用“深度顯卡驅動管理工具”更換驅動也是如此。後來我就決定,自己爲X200量身編譯一個內核。


獲取內核源碼

在Linux內核官網(https://www.kernel.org/)上,就可以下載到若干個版本的內核源碼。從官網可知,內核源碼有若干個版本,分別包括主線版(mainline)、穩定版(stable)、長期支持版(longterm)。這幾個版本的區別如下:

  • 主線版是Linux開發者活躍的地方,最新的內核功能主要在這裏誕生;
  • 穩定版是可供用戶直接使用的版本;
  • 長期支持版則主要是給設備製造商、發行版開發者使用的版本,相對更穩定,且能長期得到技術支持。

對於PC上的Linux,一般選擇穩定版,和版本大於等於4.x的長期支持版。我選擇的是4.19.1的穩定版,它出現在最醒目的位置。

內核源碼使用tar.xz格式壓縮。我將內核源碼包放置在~/kernel目錄下,然後使用以下命令解壓縮:

tar -Jxvf linux-4.19.1.tar.xz

安裝依賴

內核的編譯需要用到若干個軟件。在Deepin中,使用apt可一次性安裝好:

# 編譯工具
sudo apt install gcc make
# 語法解析器生成工具
sudo apt install bison flex
# OpenSSL庫
sudo apt install libssl-dev
# ncurses庫
sudo apt install libncurses-dev

配置內核準備

加載默認的配置文件

配置內核的第一步,就是先加載默認的配置文件以供修改。在內核解壓目錄linux-4.19中,運行:

make defconfig

默認的配置文件就會被寫入內核配置文件.config中。這裏的.config位於內核源碼根目錄,內核編譯過程用到的就是它。

執行結果如下:

anclark@anclark-PC:~/kernel/linux-4.19$ make defconfig
  HOSTCC  scripts/kconfig/conf.o
  YACC    scripts/kconfig/zconf.tab.c
  LEX     scripts/kconfig/zconf.lex.c
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
*** Default configuration is based on 'x86_64_defconfig'
#
# configuration written to .config
#

打開menuconfig

接下來的工作就是配置內核了。Linux爲我們提供了menuconfig這個配置工具,它基於ncurses與wxDialog開發,可以在其中以圖形化菜單的方式配置各種內核選項。

運行以下命令,即可自動編譯並啓動menuconfig:

make menuconfig

稍等片刻,終端中就會出現如下畫面:

menuconfig的操作方法簡單直觀,在界面上部就已經列出了,改變選項值除了按“Y/N/M”三個鍵之外,還可用空格。可以鍵入問號(即Shift+問號鍵)來查看幫助,鍵入斜槓(/)來檢索設置項。

值得注意的是,一些組件在編譯時可以選擇將其編譯到內核中(顯示爲[*]<*>)或是編譯爲模塊(顯示爲[M]<M>)。編譯到內核中就成爲了內核的一部分;而編譯成爲模塊則會被安裝到指定的目錄中,使用modprobe等工具加載。

配置內核

啓用設備支持

要想讓內核比較完美地支持目標設備,還需對內核進行一番設置。Linux官方雖然提供了針對PC的通用配置文件,但該配置文件僅僅是一個開始,要面向各種各樣複雜的具體平臺,內核的發佈者不可能兼顧所有的設備。因此,僅僅使用默認的配置文件是不夠的。

啓用無線網絡支持

考慮到不同的設備使用不同的無線網卡,默認配置文件並沒有啓用無線網卡的設備驅動。爲此還需手動開啓。

首先使用lspci命令,列出所有安裝在PCI總線上的設備,查看網卡型號:

anclark@anclark-PC:~/kernel/linux-4.19$ lspci
00:00.0 Host bridge: Intel Corporation Mobile 4 Series Chipset Memory Controller Hub (rev 07)
00:02.0 VGA compatible controller: Intel Corporation Mobile 4 Series Chipset Integrated Graphics Controller (rev 07)
00:02.1 Display controller: Intel Corporation Mobile 4 Series Chipset Integrated Graphics Controller (rev 07)
00:03.0 Communication controller: Intel Corporation Mobile 4 Series Chipset MEI Controller (rev 07)
00:03.3 Serial controller: Intel Corporation Mobile 4 Series Chipset AMT SOL Redirection (rev 07)
00:19.0 Ethernet controller: Intel Corporation 82567LM Gigabit Network Connection (rev 03)
00:1a.0 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #4 (rev 03)
00:1a.1 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #5 (rev 03)
00:1a.2 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #6 (rev 03)
00:1a.7 USB controller: Intel Corporation 82801I (ICH9 Family) USB2 EHCI Controller #2 (rev 03)
00:1b.0 Audio device: Intel Corporation 82801I (ICH9 Family) HD Audio Controller (rev 03)
00:1c.0 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 1 (rev 03)
00:1c.1 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 2 (rev 03)
00:1c.2 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 3 (rev 03)
00:1c.3 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 4 (rev 03)
00:1d.0 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #1 (rev 03)
00:1d.1 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #2 (rev 03)
00:1d.2 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #3 (rev 03)
00:1d.7 USB controller: Intel Corporation 82801I (ICH9 Family) USB2 EHCI Controller #1 (rev 03)
00:1e.0 PCI bridge: Intel Corporation 82801 Mobile PCI Bridge (rev 93)
00:1f.0 ISA bridge: Intel Corporation ICH9M-E LPC Interface Controller (rev 03)
00:1f.2 SATA controller: Intel Corporation 82801IBM/IEM (ICH9M/ICH9M-E) 4 port SATA Controller [AHCI mode] (rev 03)
00:1f.3 SMBus: Intel Corporation 82801I (ICH9 Family) SMBus Controller (rev 03)
03:00.0 Network controller: Intel Corporation PRO/Wireless 5100 AGN [Shiloh] Network Connection
04:00.0 Memory controller: Intel Corporation Turbo Memory Controller (rev 11)

在列出的設備中,無線網卡對應的是03:00.0 Network controller: Intel Corporation PRO/Wireless 5100 AGN [Shiloh] Network Connection,從中不難得知,我X200無線網卡的型號是Intel 5100AGN。

然後在menuconfig中,依次進入以下選項:

  • Device Drivers
    • Network device support
      • Wireless LAN

其中提供了很多設備的驅動選項。先找到自己無線網卡的品牌,然後找到無線網卡型號所對應的項目,按空格鍵選擇“M”編譯爲模塊。當然,如果確定驅動程序沒有問題,也可以選擇“*”編譯爲內核的一部分,不過這樣就不能使用modprobe工具手工裝載卸載以便調試了。

以筆者的Intel 5100AGN爲例。首先找到Intel所對應的項目,如下圖所示。特別的是,筆者的5100AGN對應的驅動項目是iwlwifi,即列表中的Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi)這一點從該項的幫助信息中可以知悉——遇到無法確認的項目,不妨查看它的幫助信息,以瞭解它支持什麼型號。

同時,英特爾無線網卡的工作還需要固件(firmware)的支持,因此下面的兩項關於固件的項目也選擇上。

注意事項
在筆者的X200上,如果此處英特爾無線網卡的驅動型號同時選擇多個,會有不能加載固件的情況出現,不能加載固件就意味着不能啓動無線網卡。即便將固件下載站中正確的固件放置到指定位置(/lib/firmware/),也無法啓動網卡。因此,只能選擇iwlwifi

啓用聲卡支持

同樣默認地,默認配置文件並未啓用聲卡支持,因此用編譯出來的內核啓動系統,是沒有聲音的。Linux內核使用ALSA作爲音頻框架,聲卡驅動作爲編解碼器(codec)被加載,需要我們手動把聲卡的codec選項打開,纔可在Deepin中聽到聲音。

在menuconfig中,依次進入以下選項:

  • Device Drivers
    • Sound card support
      • Advanced Linux Sound Architecture

其中又包括若干個關於聲卡驅動的子菜單,包括Generic sound devices(標準音頻設備)、PCI sound devices(PCI音頻設備)、HD-Audio、USB sound devices(USB音頻設備)和PCMCIA sound devices。現在新的筆記本和臺式機聲卡基本上都使用HD Audio控制器,包括筆者的X200,因此選擇HD-Audio。

特別的是,在Linux中,HD Audio音頻的實現由芯片組廠商(如Intel、AMD、NVIDIA)負責,因此使用lspci是看不到聲卡品牌和型號的。不過不用擔心,在HD-Audio這一列表中,一個品牌的所有HDA聲卡都遵循同一套API標準,所以可以以一個選項覆蓋所有型號。而就品牌而言,現在的筆記本多使用Realtek(瑞昱)和Conexant(科勝訊,已被Synaptics收購)的聲卡,所以選擇它們對應的兩項即可。另外,如果筆記本附帶HDMI或DisplayPort接口,則還要選上Build HDMI/DisplayPort HD-audio codec support,以從這兩種視頻輸出接口中輸出音頻信號。

至於編譯模式,最好將它們編譯成內核的一部分,因爲相較於無線網卡,聲卡的折騰要容易不少,電腦聲卡出問題的概率會低得多。

啓用用戶態文件系統支持

包括Deepin在內的發行版,爲了方便用戶使用,以及照顧雙系統用戶的需求,都支持Windows和Mac的文件系統,如NTFS、exFAT、HFS+。通常對於這些文件系統的支持,多基於FUSE(Filesystem In UserSpacE,用戶態文件系統),配合訪問這些文件系統的驅動層,如ntfs-3g。

值得注意的是,默認情況下,用戶態文件系統並沒有在默認配置文件中啓用,必須要手動打開該功能才行。打開的方法很簡單,該選項位於menuconfig主頁面的“File systems”中,項目名爲FUSE (Filesystem in Userspace) support,如下圖所示:

務必把它編譯成內核的一部分,而不是模塊,以實現Linux對FUSE的無縫支持,這對系統體驗的提升是不可或缺的。

保存內核配置

內核配置默認保存在內核源碼根目錄的.config文件中,內核編譯過程會使用它,因此menuconfig默認也會將修改好的配置文件保存在那裏。按左右方向鍵,在底部的按鈕中選擇“Save”,選擇內核配置文件的保存位置(默認爲.config),回車。若要退出,選擇“Exit”即可。

筆者建議將好不容易編輯好的內核配置導出,以便下次使用。直接把內核源碼根目錄的.config複製到別處。下次若要使用,直接將導出的配置文件覆蓋內核源碼根目錄的.config文件即可。

編譯內核

配置工作完成後,我們就可以着手開始編譯內核了,同時編譯完成後的內核與模塊可以直接安裝到系統中,下次啓動就可以直接使用我們新的內核。

開始編譯

首先確保內核已經配置好——源碼根目錄有.config文件,然後運行以下命令,開始編譯:

make

如果想提高一下編譯效率,可以加上-j參數,多開編譯進程:

make -j8

稍等一段時間,等待編譯完成。完成時,make會輸出以下信息:

Kernel: arch/x86/bzImage is ready (#2)

安裝內核模塊

內核編譯好之後,可以直接運行make install進行安裝。但是經我實測,直接安裝容易出錯,出錯的地方主要位於在內核模塊的安裝上。因此,最好先安裝內核模塊。

安裝內核模塊,只需要一個命令:

sudo make modules_install

運行該命令會調用depmod工具——配置內核模塊的工具。不同版本內核的模塊必須分別存放在內核對應的目錄中,depmod工具可以自動創建新的內核所對應的模塊目錄,然後將模塊安裝到其中。

安裝內核

安裝內核到系統中,只需要一個命令:

sudo make install

該命令會自動調用內核源碼中的安裝工具,將內核複製到系統中,在Grub菜單項中加入新內核所對應的啓動選項,並備份舊版本內核。安裝成功後,下次啓動就會自動使用我們編譯好的新內核了,同時還可以在啓動菜單的“高級啓動選項(Advanced boot options)”中選擇舊版本的內核啓動。

安裝頭文件

如果你需要做Linux相關的開發,也可以將內核頭文件安裝到系統中。只需使用一個命令:

make headers_install

編譯清理

編譯後,如果對內核源碼進行了一些修改,或是同一個內核源碼用來給多個設備進行編譯,一般都需要進行一番清理。

清理的命令有兩個:

make clean
make distclean

它們的區別在於,make clean只會清理編譯輸出的文件,如*.o(目標代碼)、*.cmd(編譯命令記錄)等,而保留當前內核的配置文件,便於重新編譯;而make distclean的清理則比較徹底,會將內核配置文件、內核配置程序的可執行文件等(如menuconfig的可執行文件)一併清除。

注意事項:
在Deepin中,由於我們在安裝內核的過程中使用了sudo,這會使得內核源碼目錄中的一些文件只有使用Root權限才能被修改。因此清理和編譯的命令也需要sudo,否則會因權限不足而中止。

測試新的內核

內核安裝完成後,重啓電腦就會默認使用新內核啓動。爲了保證內核無故障運行,我需要對內核進行一番測試。以下是我在我的X200上進行測試的過程。但在實際操作中,由於無前人的經驗,我只能摸着石頭過河,發現一個問題,解決一個問題。以下是我對整個測試過程的總結。

顯示:檢查關蓋花屏問題是否解決

很簡單,關閉蓋子重新打開,移動鼠標,以及休眠後喚醒,移動鼠標。可以發現,花屏問題完美解決,原先閃屏撕裂的狀況不再出現,終於可以愉快地吃上Deepin了。

無線網卡:檢查連接性

老款的ThinkPad有一個很貼心的設計——燈條,這是我當時選擇它的原因。燈條上電源、硬盤、網卡、藍牙工作的狀態一應俱全,方便而直觀,貼心程度至今難以被後來者超越。尤其是無線網卡,會在啓動後亮起,並在有網絡流量時閃爍。

無線網卡未加載時,Deepin系統的狀態欄中並不會出現無線網絡的圖標,同時X200的無線網卡燈不會亮起。這使我非常納悶,畢竟測試的時候我曾經嘗試同時啓用過多個型號的驅動。

後來我嘗試分析內核日誌,使用dmesg | grep iwl獲取Intel無線網卡相關的日誌信息,結果發現了下面的錯誤提示:

Direct firmware load for iwlwifi-5000-5.ucode failed with error -2
Direct firmware load for iwlwifi-5000-4.ucode failed with error -2
Direct firmware load for iwlwifi-5000-3.ucode failed with error -2
Direct firmware load for iwlwifi-5000-2.ucode failed with error -2
Direct firmware load for iwlwifi-5000-1.ucode failed with error -2
No suitable firmware found!

後來,我嘗試在Intel固件發佈頁面中下載了與我無線網卡對應的上述固件文件,放置於/lib/firmware中,結果重啓後還是會提示上述的錯誤。

於是,我回到menuconfig中,得知對應我設備的Intel驅動選項其實是iwlwifi,而不是列表中其他的那些型號。果然,取消勾選其他型號,只保留iwlwifi,重新編譯並安裝內核,問題解決,久違的無線網卡指示燈終於歡快地亮起了。

測試聲卡

測試聲卡的過程相對要順利一些,也更簡單。起初電腦放不出聲音,在Deepin設置中的“聲音”→“高級設置”中設備列表是空的。然後在內核中打開聲卡驅動相關的選項,重新編譯之後,聲音播放就正常了。

Chrome打開網易雲音樂,隨便放首歌,是最直觀的測試方法。

測試文件系統

筆者將X200原裝的硬盤拆下來改爲移動硬盤,並給筆記本換上固態,把原裝硬盤格式化爲exFAT。在啓用FUSE之前,插上原裝硬盤,Deepin雖然能識別出來,卻無法掛載,顯示爲空。後來啓用FUSE後,果然能正常識別並自動掛載了,任務欄上也出現了安全彈出的圖標。

測試USB

筆者的另一臺新的惠普筆記本,在Ubuntu 16.04上曾使用4.18版本的stable內核源碼,結果USB無法使用。有鑑於此,我在X200上還需對USB功能單獨測試。使用lsusb命令檢查USB設備連接,果然有輸出;然後插入鼠標、鍵盤、移動硬盤等USB設備,果然正常識別出來了。由此說明,4.19內核在X200上的USB功能不存在問題。

總結

和Windows不同,玩Linux的意義在於折騰。驅動問題上,Windows的解決是最爲到位和全面的,只需下載驅動安裝文件安裝即可,並且廠商也會優先支持Windows;而Linux上必須好好折騰一番,就像我這樣不停地編輯配置編譯內核,才能用上順手好用的系統。Linux雖說麻煩一些,可是折騰之後設備跑起來的成就感,卻是難以比擬的。

與此同時,筆者也意識到,很多問題的解決,還是要靠自己。對於Deepin官方內核在X200上顯示的Bug,筆者曾在Deepin論壇和反饋平臺中反饋,但幾乎沒人有有效的回覆,終究還是靠我自己解決。而且我稍微檢索了一下百度,結果沒找到任何前人的經驗,找到的只是問題最基本的排查方法而已。要是等着別人爲我想辦法,那難度可堪比登天了。自己動手,豐衣足食,正是硬道理!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章