专栏/如何让WSL2使用自己编译的内核

如何让WSL2使用自己编译的内核

2020年12月01日 13:02--浏览 · --点赞 · --评论
粉丝:2033文章:6

B站咋不支持直接导入.md文档呀,那我就直接复制粘贴我ZH上的回答了~这样居然还挺方便的哈哈哈

如何让WSL2使用自己编译的内核

写在前面 | 前置知识

近日,操作系统实验课程布置了第一项任务——编译Linux的内核。

由于编译Linux内核需要用到Linux下的各种库,因此我们很难在Linux以外的操作系统进行内核的编译。

大多同学选择使用虚拟机,通过安装一个Ubuntu之类的操作系统来编译内核。

那么,如果我不想只为了编译一个内核而安装一个新的操作系统呢



比如使用WSL,实现直接在Windows下编译Linux内核

有一点是利用常识就能知道的:在Windows下跑的Linux的内核,必然经过微软修改过的


显眼的"microsoft-standard"


但无论如何,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-VWindows虚拟机监控程序平台两项



注:如果使用的是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.9.9版本的WSL2


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

Enjoy it!


投诉或建议