Ubuntu 下编译 Linux 内核

前几天折腾路由,想给自己的斐讯 K3 编译一个固件,看了下基本上和编译 Linux 操作差不多,平时需要自己编译内核的时候总是要翻资料,写篇博客加深一下印象吧。

这里就以 google-bbr v2alpha 分支为例。

TCP BBR是由来自 Google 的 Neal Cardwell 和 Yuchung Cheng 发表的新的 TCP 拥塞控制算法,在 linux kernel 4.9 正式发布。起初接触到 BBR 是用于爱国上网,相对于 kcptun,finalspeed,锐速等,BBR 是 TCP 单边加速,且不通过暴力发包来加速(不公平,且消耗大量流量),使用简单,不会被一些 ISP 因为 UDP 而丢包。然而,dog250 大神提到了 TCP BBR 初版的两个问题:在高丢包率下易失速以及收敛慢。 在实际使用过程中,的确发现 TCP BBR 在网络高峰期不稳定,且速度是从一个比较低的速度开始缓慢增加,到全速需要很长时间,在网络情况较好时,甚至不如 cubic。网上搜寻时发现 Google 开发了 TCP BBRv2,目前处于 alpha 阶段。

一些准备工作

这里的编译环境是 Ubuntu 19.10,Debian 或者基于 Debian 的发行版应该都是差不多的步骤。

首先,安装依赖的软件包

1
2
apt update -yqq
apt install -y build-essential openssl git bison libncurses-dev bc pkg-config flex screen -yqq

接着,下载内核源码,-b v2alpha 指的是 v2alpha 分支 ,–depth=1 指的是只下载最近一次 commit,bbr 仓库很大,全部 clone 下载有时候会报错。

1
2
git clone -o google-bbr -b v2alpha  https://github.com/google/bbr.git --depth=1
cd bbr

在一般情况下,可以去 Linux 内核官网 下载 Linux 内核源码并解压。 比如 linux-5.5-rc1,可以这样。

1
2
3
wget https://git.kernel.org/torvalds/t/linux-5.5-rc1.tar.gz
tar xvf linux-5.5-rc1.tar.gz
cd linux-5.5-rc1

配置内核,生成 config 文件

配置内核有四种方法:

  • make config (基于文本的配置界面)
  • make menuconfig (基于文本菜单的配置界面)
  • make xconfig (基于图形窗口的配置界面)
  • make oldconfig (基于原来内核配置的基础上修改)

有图形界面的情况下,可用 make xconfig,基于窗口操作十分友好。make menuconfig 相对比较友好,又是基于文本菜单,所有的发行版都可以使用,所以这里推荐使用 make menuconfig。

1
make menuconfig

这里有 Linux 内核所有的设置选项。具体操作是:

1
2
3
4
5
6
Arrow keys navigate the menu.
selects submenus ---> (or empty submenus ----)
Highlighted letters are hotkeys
Pressing <Y> includes, < >excludes, <M>modularizes features
Press <ESC> to exit, <?>for Help, </>for Search
Legend: [*] built-in [] excluded module < > module capable
  • 翻译一下就是,使用 左(←)、右(→)箭头切换底部菜单,上(↑)、下(↓)箭头切换中间的配置项。
  • 带 [] 的是设置项,有四种状态,分别
    • [*] 编译进内核
    • [] 不编译
    • 作为模块编译,动态加载
    • < > 可以作为模块,但是不编译
  • 空格键 设置配置项,部分配置项右边有 —> 标识,代表有下级子项,可以使用 Enter 进去选择。

我们要启用 BBR2,则进入 Networking support(网络支持) —> Networking options(网络选项)—> TCP: advanced congestion control(TCP 高级拥塞控制)—> ,这里编译进内核, 将 BBR2 TCP 标为 [*] 。(如果你想将 BBR2 TCP 作为 model 安装,则在 BBR2 TCP 前标上 )然后把 BBR2 设置为 default(作为模块不能设置为默认)。

其他默认,保存后一路 Exit 即可。

编译内核

由于编译需要的时间比较长,我们可以用 screen 新建一个 terminal,我们可以这样我们即使我们断开 ssh 连接,之后也可以恢复。

新建一个叫 kernel 的 screen

1
screen -S kernel

开始编译内核吧。

1
make -jN deb-pkg #N 为线程数,make deb-pkg 默认单线程

这时候,我们可以 Ctrl+a+d 离开这个 screen,然后去干点别的,编译内核可能需要很长的时间。

如何回到我们刚刚的 screen:

1
screen -r kernel

在结束编译后

1
exit

即可把这个 screen 销毁。

安装内核

1
cd .. && ls

会到上级文件夹,正常情况下,编译完成后,会产生类似文件:

1
2
3
4
5
6
7
8
linux-5.4.0-rc6\_5.4.0-rc6-1.diff.gz  
linux-5.4.0-rc6\_5.4.0-rc6-1.dsc
linux-5.4.0-rc6\_5.4.0-rc6-1\_amd64.buildinfo
linux-5.4.0-rc6\_5.4.0-rc6-1\_amd64.changes
linux-5.4.0-rc6\_5.4.0-rc6.orig.tar.gz
linux-headers-5.4.0-rc6\_5.4.0-rc6-1\_amd64.deb
linux-image-5.4.0-rc6\_5.4.0-rc6-1\_amd64.deb
linux-libc-dev\_5.4.0-rc6-1\_amd64.deb

安装

1
dpkg -i *deb

查看已经安装的内核,并把旧的卸载了

1
2
dpkg -i | grep linux
apt purge 旧的 linux-headers linux-image

接着重启即可

1
reboot

BBR2 的一些相关操作

如果前面没有把 BBR2 设置为默认的协议,那么需要修改一下:

1
2
3
echo "net.core.default_qdisc = fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control = BBR2" >> /etc/sysctl.conf
sysctl -p

如果你想要开启ECN(默认的「net.ipv4.tcp_ecn」为 2,即「 传入连接请求时启用 ECN,但不在传出连接上请求 ECN 」)

1
2
3
echo "net.ipv4.tcp_ecn = 1" >> /etc/sysctl.conf
echo "net.ipv4.tcp_ecn_fallback = 1" >> /etc/sysctl.conf
sysctl -p

检查是否开启 BBR2

1
2
sysctl net.ipv4.tcp_available_congestion_control
sysctl net.ipv4.tcp_congestion_control

如果结果都有 BBR2,则证明你的内核已开启 BBR2。

以模块编译的话也可以执行 lsmod | grep BBR2,看到有 BBR2 模块即说明 BBR2 已启动