在WSL2中编译安装SocketCAN内核模块
有的人恨不得三个手机(Work.Android,Work.iOS,Private.Anyway),有的人恨不得三台电脑(Windows, Linux, MacOS)。有过几次出差,来回背两台电脑的经历后,下决心安装WSL双系统,各种钻研已经耗费了一周时间,希望以下日志能给大家省点时间。
SocketCAN简介
Linux下CAN总线开源项目
can-utils应用程序
可以直接通过apt命令安装3,常用的命令如:candump显示收到的CAN报文,isotpdump解析isotp传输协议层数据。
$ sudo apt-get install can-utils
$ apt info can-utils
Package: can-utils
Version: 2018.02.0-1ubuntu1
...
This package contains some userspace utilities for Linux SocketCAN subsystem.
.
Basic tools to display, record, generate and replay CAN traffic:
candump, canplayer, cansend, cangen, cansniffer.
CAN access via IP sockets: canlogserver, bcmserver, socketcand.
CAN in-kernel gateway configuration: cangw.
CAN bus measurement and testing: canbusload, can-calc-bit-timing, canfdtest.
ISO-TP (ISO 15765-2 2016) tools: isotpsend, isotprecv, isotpsniffer,
...
找一款合适的CAN硬件
便宜的某宝上很多,这里推荐ValueCAN,相对个人玩家小贵,但好在汽车工程师圈子中比较常见,公司现成资源4,且软件资源相对开放。
WSL2双系统
汽车电子工程师基本都在Windows环境下工作,以前需要用Linux的机会很少,因为大多数嵌入式开发和测试标定的工具都是Windows版本。但汽车上的智能终端(Linux)和大数据服务(Backend)兴起后,软件代码量和复杂度都越来越高,相应的Linux下的开源代码和开源工具也渗透到汽车研发领域。双系统(Windows+Linux)正成为很多汽车电子工程师的标配。
WSL2就是Windows下的Linux虚拟机5,目前Hypervisor虚拟化技术在汽车上多核仪表、导航里也在大量使用,Microsoft在之前发布的WSL的基础上做了升级6,执行效率和构建方式上都有很大变化。
安装Ubuntu虚拟机
在Windows启动Ubuntu,需要先通过管理员模式启动PowerShell,安装WSL2。
WSL2的安装网上有很多参考7,如果之前安装过WSL,也可以升级到WSL2。
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
wsl --set-default-version 2
然后通过Microsoft Store安装最新版本的Ubutnu,速度一般都非常快
检查当前内核版本
WSL2所使用的Linux内核版本为 4.19.128-microsoft-standard(发布时间 09/15/2020)
$ uname -r
4.19.128-microsoft-standard
$ cat /proc/version
Linux version 4.19.128-microsoft-standard (oe-user@oe-host) (gcc version 8.2.0 (GCC)) #1 SMP Tue Jun 23 12:58:10 UTC 2020
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.1 LTS
Release: 20.04
Codename: focal
Ubuntu下通过apt默认安装的内核模块库在lib/modules目录下,如果uname -r的内核版本目录在lib/modules下找不到,会造成后面内核模块编译和安装的问题!
$ ls -al /lib/modules
$ apt search linux-headers-4.19.43-microsoft-standard
Sorting... Done
Full Text Search... Done
$ sudo apt install linux-headers-generic build-essential
$ ls -al /lib/modules
5.4.0-47-generic
遗憾是的是通过apt install在软件库中找不到对应wsl2内核库文件,需要通过下载内核源码8编译安装。
下载内核源码
从之前uname -r命令我们知道了内核版本4.19.128-microsoft-standard,从GitHub发布页8上找到该版本,下载后解压
$ wget https://github.com/microsoft/WSL2-Linux-Kernel/archive/4.19.128-microsoft-standard.zip
$ 7za x 4.19.128-microsoft-standard.zip
...
Physical Size = 204995661
Comment = 2710823ef37b91be416f0507d2f6e72ce78673af
也可以直接git clone复制对应版本分支
$ git clone --branch $(uname -r) --depth 1 https://github.com/microsoft/WSL2-Linux-Kernel.git
$ cd 4.19.128-microsoft-standard
下载速度慢的参考网盘备份:链接:https://pan.baidu.com/s/1JN06qRaYLmmF5MK7cqe03Q 提取码:6zvp
配置Linux内核
解压后的内核源码可以尝试用如下默认配置编译一下,会按该版本的默认配置生成zImage文件。
$ make KCONFIG_CONFIG=Microsoft/config-ws -j $(nproc)
如果不希望使用默认模块配置,可以从当前系统内核配置中拷贝并配置.config内核模块配置文件。
$ cd 4.19.128-microsoft-standard
$ zcat /proc/config.gz > .config
检查所需的内核模块是否已经打开配置开关,例如CAN Bus内核模块。
$ zcat /proc/config.gz |grep -i CONFIG_CAN
# CONFIG_CAN is not set
WSL和WSL2默认都不带CONFIG_CAN9,如果要把CAN模块加进入一起编译,直接编辑.config文件,添加 “CONFIG_CAN=y” 编译开关。
$ zcat /proc/config.gz |grep -i CONFIG_CAN
# CONFIG_CAN is not set
CONFIG_CAN=y
编译Linux内核
下载编译内核所需的工具。
$ sudo apt-get install bison build-essential flex libssl-dev libelf-dev bc
$ sudo apt-get install libelf-dev pkg-config
电脑有多核的可以用多核并行编译,一般都比较耗时,8核PC约需30m。
如果额外配置了CAN模块,会提示与SocketCAN相关的子模块配置要求,一直回车确认默认配置就好。
顺利的话,会提示生成bzImage内核镜像文件,否则检查编译过程error。
常见问题包括:下载的wsl kernel源码不完整,解压过程出错10等。
$ make -j $(nproc)
scripts/kconfig/conf --syncconfig Kconfig
.config:1351:warning: override: reassigning to symbol CAN
*
* Restart config...
*
* CAN bus subsystem support
*
CAN bus subsystem support (CAN) [Y/n/m/?] y
Raw CAN Protocol (raw access with CAN-ID filtering) (CAN_RAW) [Y/n/m/?] (NEW)
Broadcast Manager CAN Protocol (with content filtering) (CAN_BCM) [Y/n/m/?] (NEW)
CAN Gateway/Router (with netlink configuration) (CAN_GW) [Y/n/m/?] (NEW)
*
* CAN Device Drivers
*
Virtual Local CAN Interface (vcan) (CAN_VCAN) [N/m/y/?] (NEW)
Virtual CAN Tunnel (vxcan) (CAN_VXCAN) [N/m/y/?] (NEW)
Serial / USB serial CAN Adaptors (slcan) (CAN_SLCAN) [N/m/y/?] (NEW)
Platform CAN drivers with Netlink support (CAN_DEV) [Y/n/m/?] (NEW)
CAN bit-timing calculation (CAN_CALC_BITTIMING) [Y/n/?] (NEW)
......
CAN devices debugging messages (CAN_DEBUG_DEVICES) [N/y/?] (NEW)
......
安装内核镜像
默认安装wsl2时,加载的是如下位置的Linux Kernel Image。
$ ls -alh /mnt/c/Windows/System32/lxss/tools/kernel
-r-xr-xr-x 1 xxx xxx 59M Jul 8 14:31 /mnt/c/Windows/System32/lxss/tools/kernel
$ file /mnt/c/Windows/System32/lxss/tools/kernel
/mnt/c/Windows/System32/lxss/tools/kernel: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=be29821b14c3110ddd5ae78f358828cab501c5bb, not stripped
也可以通过.wslconfig文件,配置使用之前编译好的内核镜像文件。
如果之前的Linux内核编译顺利的话,通过如下命令重定向到自编译的内核固件来启动。
# 内核文件不大,可以找个系统固态硬盘存储加载,一般是C盘,如/mnt/c/wslkernel
$ mkdir -p /mnt/c/wslkernel/
# 将上面编译好的内核固件,拷贝到指定目录,并重命名
$ cp arch/x86/boot/bzImage /mnt/c/wslkernel/4.19.128-microsoft-standard_with-can
# 编辑wls2的配置文件wslconfig,添加上默认加载的内核固件位置,注意使用Win路径分隔符
$ vim /mnt/c/Users/<username>/.wslconfig
[wsl2]
kernel = C:\\wslkernel\\4.19.128-microsoft-standard_with-can
构建内核模块
构建安装过程中,配置CONFIG_CAN=y开关可以将socketcan相关的can.ko等模块链接到Linux内核镜像文件中。
有些usb设备不在标准内核里面,如果想在WSL下使用这类热插拔接口设备,就需要编译设备的驱动。这些驱动模块一般以内核模块的方式加载到系统中。
如果想让can.ko, can_raw.ko单独存在,在内核启动后动态加载,配置时使用CONFIG_CAN=m参数。
$ echo CONFIG_CAN=m >> .config
$ make -j $(nproc) modules
# select m for CAN_RAW, CAN_BCM, CAN_GW, CAN_VCAN, CAN_SLCAN, CAN_DEV
$ sudo make modules_install
# 该命令会将编译好的ko内核模块,拷贝至/lib/modules对应版本目录下
$ find /lib/modules/`uname -r` -iname "*" -type f
$ sudo depmod -v
/lib/modules/4.19.128-microsoft-standard/kernel/net/can/can-raw.ko needs "can_rx_unregister": /lib/modules/4.19.128-microsoft-standard/kernel/net/can/can.ko
/lib/modules/4.19.128-microsoft-standard/kernel/net/can/can-bcm.ko needs "can_rx_unregister": /lib/modules/4.19.128-microsoft-standard/kernel/net/can/can.ko
/lib/modules/4.19.128-microsoft-standard/kernel/net/can/can-gw.ko needs "can_rx_unregister": /lib/modules/4.19.128-microsoft-standard/kernel/net/can/can.ko
$ dmesg | tail
然后就是在WSL下编译新设备内核驱动的过程。以上文提到的ValueCAN为例11
开源工具箱测试
TODO
问题记录跟踪
unzip解压错误
一般是文件名过长,或文件中存在符号链接,解决办法之一是使用7z软件10,用7za x解压。也可以github上下载tar.gz文件,然后在wsl下tar xvzf解压。
modprobe can导致wsl终端退出
暂无调试和解决方案,详见 12
参考链接
http://blog.csdn.net/zhangxiaopeng0829/article/details/7646639 ↩︎
https://www.kernel.org/doc/Documentation/networking/can.txt ↩︎
https://github.com/linux-can/can-utils ↩︎
http://www.vehinfo.com/product-item-16.html ↩︎
https://blog.csdn.net/spacecraft/article/details/50540019 ↩︎
https://microhobby.com.br/blog/2019/09/21/compiling-your-own-linux-kernel-for-windows-wsl2/ ↩︎
https://docs.microsoft.com/en-us/windows/wsl/install-win10 ↩︎
https://github.com/microsoft/WSL2-Linux-Kernel/releases ↩︎ ↩︎
https://github.com/microsoft/WSL/issues/5533 ↩︎
https://blog.csdn.net/yeyiqun/article/details/96941553 ↩︎ ↩︎
https://github.com/telehan/intrepid-socketcan-kernel-module ↩︎
https://github.com/microsoft/WSL2-Linux-Kernel/issues/194 ↩︎