WSL可以自己編譯新的Linux核心給自己用!
Microsoft開發的WSL雖然功能眾多,但仍不支援載入核心模組(kernel modules)的功能,所有驅動模塊都是編譯在核心裡的。所以若核心需要支援某個功能,多半得重新編譯(recompile)核心了。
譬如,我想 在WSL跑Android容器,就需要用到memfd的核心選項,那麼只要取得Microsoft公開的WSL核心原始碼,將特定功能開啟,編譯核心,再將WSL使用的核心抽換掉就好啦。
甚至,如果想搶先體驗最新版主線Linux的核心功能,您也可以自行從 kernel.org下載原始碼自行編譯,並給WSL裝上!
本文以WSL預設的Ubuntu為例子,示範如何在WSL裡編譯核心,開啟自訂選項,再替換掉原本的WSL核心。
1. 編譯核心前的準備#
確保已安裝 WSL
登入WSL
wsl -d Ubuntu
- 安裝編譯核心用的套件
sudo apt update
sudo apt install wget build-essential bison flex libncurses-dev libssl-dev libelf-dev bc pahole
- 取得核心原始碼。Microsoft的原始碼會公佈在 Github儲存庫。下載之前需要先確認目前WSL使用的核心版本:
uname -a
- 假設輸出
5.15.90.1
,那麼就從Github下載5.15.90.1的核心,並解壓縮
wget https://github.com/microsoft/WSL2-Linux-Kernel/archive/refs/tags/linux-msft-wsl-5.15.90.1.tar.gz
tar -xvf linux-msft-wsl-5.15.90.1.tar.gz
cd WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1
2. 編輯核心功能#
- 首先將WSL的核心設定檔複製出來,使用x86架構的設定檔
cp Microsoft/config-wsl .config
- 啟動menuconfig編輯核心選項,切勿直接編輯
.config
檔案。
make menuconfig
現在會看到一個灰色畫面,這個就是用來調整核心功能的界面。操作方式:使用鍵盤的箭頭上下移動,按Enter進入下一級選單,按空白鍵啟用/關閉該核心功能。
如果不知道要啟用的核心選項在哪,按
/
,鍵入CONFIG的字串,按Enter,它就會告訴你該選項的位置。如下圖,CONFIG_IPV6_ROUTER_PREF
要到Networking support
下的The IPv6 protocol
勾選啟用,使其變成[y]
。如果記不起來位置,可以選取終端機文字,按Ctrl+C複製到記事本對照看。如果不知道確切要開哪個核心選項,請搜尋「CONFIG_XXX + Gentoo Wiki」就會有很多資料。
編輯完核心功能後,用鍵盤左右鍵移動到
Save
,按Enter,儲存設定檔。接著開始編譯核心。
-j$(nproc)
代表使用全部CPU執行緒編譯,大約要30分鐘。
make -j$(nproc)
- 編譯後的檔案是
bzImage
,應位於/arch/x86/boot/
資料夾。
3. 給WSL裝上編譯好的核心#
我們可以利用.wslconfig
指定WSL啟動時要載入的核心,這樣就不用去動WSL的系統檔案了。
開啟檔案總管,點選檢視 → 顯示隱藏項目,點選左下角的「Linux」,到
Ubuntu\home\user\WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1\arch\x86\boot\
資料夾,剪下bzImage
檔案將
bzImage
移動到任意資料夾,例如C:\Users\使用者名稱\wslcustomkernel
在使用者家目錄(
C:\Users\使用者名稱\
),右鍵新增.wslconfig
檔案右鍵用記事本開啟
.wslconfig
,輸入以下內容儲存。kernel
代表核心bzimage所在的硬碟資料夾。
[wsl2]
kernel=C:\\Users\\使用者名稱\\wslcustomkernel\\bzImage
- 回到WSL終端機,退出WSL
exit
- 再開一個終端機(以系統管理員執行),將WSL強制關機
taskkill /F /im wslservice.exe
wsl --shutdown
- 重新登入WSL。
wsl -d Ubuntu
- 確認核心版本是否已經成功變更
uname -v
- 範例輸出,核心編譯日期顯示為今天,代表核心已成功變更。