Linux driver について学習したいけど、LinuxPCは無いし、VirtualBoxやDualbootは起動に手間がかかるので、お手軽にWSL2でドライバを作ってみました。
※環境:Windows10
1. WSLのバージョンを確認
powershellで以下を実行。
PS C:\WINDOWS\system32> wsl -l -v
NAME STATE VERSION
* Ubuntu20.04LTS Running 2
PS C:\WINDOWS\system32>
VERSION が1であれば、wsl --set-default-version 2
で WSL2 へ update する。
(Windowsの再起動やBIOS設定の変更が必要かも)
2. WSL2のカーネルバージョンを確認
$ uname -r
5.10.60.1-microsoft-standard-WSL2+
3. WSL2カーネルソースの取得・ビルド
最終的に以下のフォルダ構成を目指します。
$ tree -d -L 2
.
└── linux_driver
├── WSL2-Linux-Kernel
└── hello
親Dirを作成、kernel source を取得。
$ mkdir linux_driver
$ cd linux_driver
$ git clone https://github.com/microsoft/WSL2-Linux-Kernel.git
clone が完了したら、branch をWSL2のカーネルバージョンと同じtagへcheckoutする。
$ cd WSL2-Linux-Kernel
$ git tag -l | grep 5.10
linux-msft-wsl-5.10.102.1
linux-msft-wsl-5.10.16.3
linux-msft-wsl-5.10.43.3
linux-msft-wsl-5.10.60.1
linux-msft-wsl-5.10.74.3
linux-msft-wsl-5.10.81.1
linux-msft-wsl-5.10.93.2
v2.6.25.10
v2.6.35.10
v3.15.10
v4.15.10
$ git checkout linux-msft-wsl-5.10.60.1
$ git branch
* (HEAD detached at linux-msft-wsl-5.10.60.1)
linux-msft-wsl-5.10.y
4. カーネルのビルド
$ sudo install build-essential flex bison libssl-dev libelf-dev
$ cd WSL2-Linux-Kernel
$ cp Microsoft/config-ws .config
$ make
→ make でエラーが起きたため、make menuconfig
が必要だった。
$ sudo apt-get install libncurses-dev
$ make menuconfig
makeをリトライ。
$ make
※30分くらいかかります
5. WSL2のカーネル設定をupdate
ビルド成果物をWindowsへコピー。
$ sudo cp arch/x86_64/boot/bzImage /mnt/c/Users/ユーザー名
以下の内容の .wslconfig を作成、C:Users/ユーザー名 へ保存。
[wsl2]
kernel=C:\\Users\\ユーザー名\\bzImage
管理者権限でpowershellを起動、wslを再起動
wsl --shutdown
6. Linuxドライバの作成
$ mkdir hello
$ cd hello
以下のhello.cとMakefileを作成する。
#include <linux/module.h>
static int hello_init(void)
{
printk("hello world.\n");
return 0;
}
static void hello_exit(void)
{
printk("Goodbye, cruel world.\n");
}
module_init(hello_init);
module_exit(hello_exit);
obj-m := hello.o
all:
make -C ../WSL2-Linux-Kernel M=`pwd` modules
clean:
make -C ../WSL2-Linux-Kernel M=`pwd` clean
※MakefileはTab文字インデントなので注意
makeを実行。
$ make
make -C ../WSL2-Linux-Kernel M=`pwd` modules
make[1]: Entering directory '/home/fokko/linux_driver/WSL2-Linux-Kernel'
CC [M] /home/fokko/linux_driver/hello/hello.o
MODPOST /home/fokko/linux_driver/hello/Module.symvers
WARNING: modpost: missing MODULE_LICENSE() in /home/fokko/linux_driver/hello/hello.o
CC [M] /home/fokko/linux_driver/hello/hello.mod.o
LD [M] /home/fokko/linux_driver/hello/hello.ko
make[1]: Leaving directory '/home/fokko/linux_driver/WSL2-Linux-Kernel'
hello.ko が出来ていれば成功。
fokko@Fokko:~/linux_driver/hello$ ls
Makefile Module.symvers hello.c hello.ko hello.mod hello.mod.c hello.mod.o hello.o modules.order
fokko@Fokko:~/linux_driver/hello$
hello.ko の対象カーネルがWSL2のカーネルと同じかチェック。
$ modinfo hello.ko
filename: /home/fokko/linux_driver/hello/hello.ko
srcversion: D0AC9F814F54BCA6F71E701
depends:
retpoline: Y
name: hello
vermagic: 5.10.60.1-microsoft-standard-WSL2+ SMP mod_unload modversions
fokko@Fokko:~/linux_driver/hello$
insmod/rmmod で driver を登録。
$ sudo insmod hello.ko
$ sudo rmmod hello
dmesg で hello/goodbye が出力されればOK。
$ dmesg | tail
[ 64.310628] WSL2: Performing memory compaction.
[ 365.318054] WSL2: Performing memory compaction.
[ 426.326189] WSL2: Performing memory compaction.
[ 547.332114] WSL2: Performing memory compaction.
[ 612.340814] WSL2: Performing memory compaction.
[ 1528.597697] hello: loading out-of-tree module taints kernel.
[ 1528.597725] hello: module license 'unspecified' taints kernel.
[ 1528.597727] Disabling lock debugging due to kernel taint
[ 1586.862607] hello world.
[ 1590.233958] Goodbye, cruel world.
追伸:
最初、insmod で insmod: ERROR: could not insert module hello.ko: Invalid module format
というエラーが出て悩んでいましたが、"5. WSL2のカーネル設定をupdate" を行って解決できました。
参考:https://unix.stackexchange.com/questions/594470/wsl-2-does-not-have-lib-modules