B站咋不支持直接导入.md文档呀,那我就直接复制粘贴我ZH上的回答了~这样居然还挺方便的哈哈哈
如何让WSL2使用自己编译的内核
写在前面 | 前置知识
近日,操作系统实验课程布置了第一项任务——编译Linux的内核。
由于编译Linux内核需要用到Linux下的各种库,因此我们很难在Linux以外的操作系统进行内核的编译。
大多同学选择使用虚拟机,通过安装一个Ubuntu之类的操作系统来编译内核。
那么,如果我不想只为了编译一个内核而安装一个新的操作系统呢

比如使用WSL,实现直接在Windows下编译Linux内核
有一点是利用常识就能知道的:在Windows下跑的Linux的内核,必然经过微软修改过的

但无论如何,WSL2上使用的内核是真正的Linux内核,因此它一定来自现有的Linux开源项目,那么我们一定有办法利用现有的Linux版本,将它通过一定的配置编译成"microsoft-stand"
事实上,通过十分简单的流程我们就可以做到让WSL2使用我们自己编译的内核:

一个示例
不过为了确保大家实验成功,我想先讲些前置知识
什么是WSL,以及WSL2的安装
如果你已经知道什么是WSL,并且知道WSL1和WSL2的区别,想直接实操,那么可以跳到 如何编译WSL2的内核 处观看。
WSL是windows subsystem for Linux
的缩写,微软通过运行一层兼容层的方法让Windows的NT内核可以运行GNU套件,使得Windows得以兼容Unix-like系统常用的POSIX接口的程序。
如果你是第一次使用WSL,你可以通过:
快捷键win
+X
->应用和功能
->程序和功能
->启用或关闭Windows功能
中打开“适用于Linux的Windows子系统”的选项。
由于本实验使用到的是WSL2,因此我们还需要打开Hyper-V
和Windows虚拟机监控程序平台
两项

注:如果使用的是15.5版本以下的VMware等版本较低的虚拟机平台,它们是不能和Hyper-V共存的,将虚拟机平台更新后便可同时使用WSL2与虚拟机
WSL1和WSL2在底层的原理完全不同,因此你必须确保你机器上跑的是version 2而不是version 1
个人理解如下:
WSL1:相当于微软实现了GNU/Windows,它并没有真正的Linux内核,而是利用Windows内核的API实现了对GNU/Linux上层的GNU套件的兼容
WSL2:拥有真正Linux内核的轻量虚拟机,因此我们才有可能对它”换内核“
同时,有必要确保你现在的电脑运行的是Windows10 2004以上的版本,只有新的Windows10可以运行WSL2
终端输入:
winver
输入以下命令可以确保新安装的Linux是WSL2而不是WSL1
wsl --set-default-version 2
接下来就可以在Microsoft Store
搜索Linux
或使用其他方式安装所需的Linux发行版了,这种教程网上有许多,本文便不进行展开
这里多嘴一句,如果不清楚别人到底叫你输入了什么命令,一般可以通过--help
等选项来查看这个命令究竟是怎么用的,比如:
wsl --help
这样我们就可以看到Windows subsystem for Linux的各种用法
比如打包、导入、导出自己的WSL环境

向下翻滚我们可以发现:如果你不想再装一个新版本的Linux,你也可以把现存的WSL1的Linux转换为WSL2

wsl --set-version ubuntu 2
对比虚拟机,使用WSL2编译内核的好处
那么,为什么要不按照老师的要求使用虚拟机编译,而是要在WSL2下编译实验一呢?
目前我发现的好处如下:
WSL2运行效率高、同时需要编译内核小,因此编译过程十分迅速。
比如,同一台使用16线程编译的电脑,在虚拟机平台我需要花费大约30分钟执行编译,而在WSL2下,我仅花费了两分钟就完成了Linux内核全新的、完整的编译
WSL2直接使用本机的内存与硬盘空间,你不会出现像因为给虚拟机平台预先分配内存不够,导致编译中途失败的情况
我在我只有8G内存,硬盘余量只剩10G的Surface Pro7上都成功执行了编译
不像在虚拟机平台下你需要拷贝本机已有配置后再编译;编译WSL2是直接使用微软的配置、直接在微软的平台下进行,不会出现像虚拟机平台一样即使编译成功了,内核也不能正常启动的情况
总结以上几点,WSL2编译的优势:
快
编译稳定
成功性高
和Windows的种种方便的集成(这个可以体现在后面的实操流程中
如何编译WSL2的内核
以下命令全都在WSL2的终端中执行!
编译的思路来自WSL2内核项目的\README-Mircrosoft.WSL2

流程概览
整体步骤与通常编译Linux内核相似,只是Makefile
使用的.config
文件来自微软;同时WSL2显然也不是用grub
启动的,因此需要在Windows的某目录下替换内核文件
由于WSL的启动目录是通常是Windows下的用户目录,其NTFS
格式很有可能令编译过程出现各种奇奇怪怪的错误,因此建议编译前最好切换到WSL2的Linux的目录下。比如在用户的家目录:
cd ~
内核下载
你可以直接浏览器下载压缩包再移到WSL2中,但这里我们使用镜像站提供的内核,这样下载会快些:
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.9.9.tar.gz tar xvzf ./linux-5.9.9.tar.gz #解压到当前目录 cd ./linux-5.9.9.tar.gz #切换到解压好的目录
设置编译配置文件
正如上面反复强调的,我们使用的是微软的配置,项目的链接:
microsoft/WSL2-Linux-Kernel: The source for the Linux kernel used in Windows Subsystem for Linux 2 (WSL2) (github.com)

我们需要的配置文件在/Microsoft/
文件夹内

在将要执行编译的工作区目录创建配置文件
touch .config
接下来我们想办法把微软配置文件的内容拷贝到.config
就完事了
比如vi .config
后,Ctrl+Shift+V 粘贴内容再保存退出
但是由于这个文件实在是太长很难直接拷贝,因此最好能使用命令行解决(但是问题是能直接显示源码的raw.github
被墙了
配置文件添加个人信息
如果你是来做作业的,那么肯定涉及”在内核版本号添加个人学号信息“的一项任务🤣
对于WSL2内核的编译,我们可以改两处地方
1. 修改Makefile
那么我们可以用记事本编辑对应的地方再保存
notepad.exe .\Makefile

没错,使用记事本打开Linux的文件,WSL就是这么的梦幻
2.修改.config
为了防止编译完后的内核号中出现-microsoft-standard
,我们还需要修改微软的.config
notepad.exe .\.config

将-microsoft-standart
替换成自己的信息再保存即可
安装编译包
正式编译前,我们还需要安装各种编译的依赖项
在WSL2内核项目的\README-Mircrosoft.WSL2
中我们可以知道所需的软件包,这里使用Ubuntu做示例

# 记得换源、更新软件包! apt update #更新源 apt install build-essential flex bison libssl-dev libelf-dev
有没有发现这里的命令全都不带sudo
?进入WSL2后用户默认就有超级用户的权限,因此WSL下通常不会出现权限问题,这也算是WSL的优点之一吧
正式编译
make -j8;make modules -j8;make modules_install -j8;make install -j8
make一把梭,由于我们目录下已经有了自己的.config
文件,因此不像官方示例一样要使用make KCONFIG_CONFIG=Microsoft/config-wsl
其实WSL2内核的编译,似乎只用一个make就行了,由于WSL2构造和普通Linux不同,似乎后面的make modules都没用。但是为了保险起见,我还是都写了
-j8
是多线程编译,可以让你编译的速度快许多(否则它只是感人的单线程)。我的Surface Pro7是4核8线程,因此使用-j8
,而我的8核16线程的电脑上则可以开-j16

编译开始后会有一堆内核编译选项,我们一路回车下去全部使用默认的即可

接着,编译就正式开始了,编译时间的长短取决于CPU的绝对性能和电脑的散热。我的Surface Pro7在编译过程中发生了比较严重的降频,最后花了12分钟才运行完

最后编译完成,注意红框处的提示。这里显示的Kernel: arch/x86/boot/bzImage is ready (#1)
就是编译后生成的内核的位置
cd ./arch/x86/boot explorer.exe .

此路径中的bzImage
就是我们编译出的WSL2的内核了
如何替换现有的内核
显然,和虚拟机不同,wsl2并不是使用grub启动的,我们需要的是替换在Windows某目录下的内核文件:
C:\WINDOWS\System32\lxss\tools

这个目录即是WSL2的启动目录,红框处的kernel
即为WSL2现有的内核
是不是感觉这个目录的结构和Linux的/boot
极为相似?
接下来我们要做的,就仅仅是把bzImage
拖到这个目录里,并且将其改名为kernel
而已
要注意给原来的kernel
备份一下哦

在Windows的终端中输入
wsl --shutdown
关闭WSL2,再重新打开终端即可
uname -r #检查内核版本

显然,我们的WSL2换上了全新的、我们自己编译的内核
接着就可以用screenfetch
或者neofetch
等工具来截图炫耀啦~
换内核前:

换内核后:

这样,我们就有了内核版本号为5.x的WSL2!
Enjoy it!