跳转至

内核

本节为非必须部分,上手需要一定的知识储备,如果你没事或者不清楚为什么搞内核,可以看下一节。

Danger

如果你的手机内核版本为5.4,那它使用了 GKI(Generic Kernel Image) 1.0,给这种设备单独编译出可用的内核几乎是不可能的, 就算能编译出来, 手机外围设备(如触摸屏,尾插等)也无法工作.

Warning

当你在执行时,因为每个人所使用的系统操作环境不同,很可能会出现不可控的奇怪报错,出现问题提问前请确保严格按照本教程操作。提问要给出详细信息和测试结果,并参考首页的提问指南

看前须知

首先,你需要确认你的手机内核是开源的(这个需要自己了解搜索信息)。

如果不开源,那就不用继续看了。

为什么自定义系统内核

我们都知道,安卓使用 Linux 内核,但是系统内核的功能被严重阉割,导致有些东西(例如 Docker)跑不起来。

这时候,我们就需要构建自己的 Linux 内核,来补全这些功能,让我们需要的软件能正常运行。

修改内核能做到的当然不止如此,在安卓上,Linux 内核扮演的角色大致相当与电脑的 BIOS+系统内核,也就是说,你还可以通过修改内核来优化性能,甚至超频。不过这就是后话了。

准备环境

编译 Linux 内核肯定是需要 Linux 的,目前有如下几种方法

  • 实机安装一个 Linux 发行版(比如 Ubuntu)

  • 使用 Windows 的 Linux 子系统v2(WSL2)安装一个Linux发行版(推荐 Ubuntu)

如果电脑配置不大行,建议实机安装。RAM 为 8G 或更低的设备一定要实机安装!

对于如何安装以上的系统不在本文主题内,如果你不懂,可以搜索一下。

本教程以 Ubuntu22.04 为例.

首先,我们要把软件源更换为国内镜像源,在终端输入以下命令:

sudo sed -i "s@http://.*archive.ubuntu.com@https://mirrors.tuna.tsinghua.edu.cn@g" /etc/apt/sources.list
sudo apt update

以上命令会将软件源更换为清华大学源。然后我们开始安装依赖,在终端输入以下命令安装依赖:

sudo apt install -y acl aptly bc bison build-essential busybox ca-certificates clang coreutils cpio crossbuild-essential-arm64 curl debian-archive-keyring debian-keyring dialog flex gawk gcc git gpg gzip initramfs-tools jq kmod libbison-dev libcrypto++-dev libelf-dev libfdt-dev libfile-fcntllock-perl libfl-dev liblz4-tool libncurses-dev libncurses5 libncurses5-dev libncursesw5-dev libpython2.7-dev libssl-dev libusb-1.0-0-dev lld llvm locales lz4 lzma lzop mtools ncurses-base ncurses-term ntpdate p7zip p7zip-full parallel patchutils pigz pixz pkg-config pv python2 python3 python3-dev python3-distutils rsync subversion swig tar udev unzip uuid uuid-dev uuid-runtime vim wget xz-utils zip zlib1g-dev zstd

旧版内核

Warning

本部分适用于旧版内核, 即 4.x 或更旧版本, 5.x 或更新版本不适用!!

准备编译器, 源码

安装完前面的依赖后,我们需要下载编译器,这里使用clang。

cd ~ && git clone --depth=1 https://github.com/kdrag0n/proton-clang.git

Help

如果克隆很慢,尝试把源地址前加上https://ghproxy.com/, 例如https://ghproxy.com/https://github.com/kdrag0n/proton-clang.git

下载完后,我们在终端输入vi ~/.bashrc打开编辑器,按下键盘上的 "Insert" 键,使用方向键滑到文件底部,加上以下代码:

export PATH="~/proton-clang/bin:$PATH"
export CROSS_COMPILE=aarch64-linux-gnu-
export CROSS_COMPILE_ARM32=arm-linux-gnueabi-
export ARCH=arm64

然后按下 “Esc” 键,输入:wq!保存退出。

接着输入以下命令 source ~/.bashrc && clang --version,它应该有大概长这样的输出(因人而异):

Proton clang version 13.0.0 (https://github.com/llvm/llvm-project b4fd512c36ca344a3ff69350219e8b0a67e9472a)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/proton-clang/bin

如果没有,说明某一步操作有问题,你必须回头纠正, 否则下面的操作无法进行。

对于源码, 你可以去 XDA开发者论坛(英文) 寻找你手机的内核源码,直接在论坛内搜索你的手机型号即可。这里的内核一般是经过大佬修改的第三方版,带有性能优化或额外功能。本人推荐去这里查找。

如果没有也别沮丧。可能只是还没人做而已。 一般来讲,小米几乎所有手机和一加所有手机的内核都是开源的。

小米开源内核目录在这里,直接查找你手机的型号即可。

一加开源内核在这里

对于初学者,在这个目录找到你手机对应的源码比较难,所以推荐直接谷歌 “一加xx内核源码”。

对于其他品牌,你可以试着谷歌 “你的手机型号+内核源码”。

准备配置并开始编译

现在环境已经准备好了,我们需要下载我们之前找到的内核源码。

本教程作为示例所使用的内核源码在这里

一般内核都使用 Git 源,我们应该通过这种方法下载:

git clone --depth=1 <源地址>

其中 --depth=1 表示浅克隆,即不克隆提交记录,因为 Linux 历史悠久,提交记录非常多(比如本教程的示例内核有86万多个提交)如果将他们克隆下来,将会非常慢,最后源码目录也会非常大。

Help

如果克隆很慢,尝试把源地址中的github.com改成hub.fastgit.xyz

克隆完成后,进入源码目录。

Warning

本教程的 Docker 支持仅仅是一个例子。你需要在此步做出你想要的修改。

为了实现 Docker 支持,我们需要修改手机内核的默认配置。 进入 arch/arm64/configs 使用 ls 命令查看一下。一般会有几个文件,还有个vendor文件夹。 例:

march7th@march7th-pc:~/crdroid_12_kernel/arch/arm64/configs$ ls -al
total 392
drwxr-xr-x 1 march7th march7th    166 Aug 13 06:22 .
drwxr-xr-x 1 march7th march7th    178 Aug 13 05:25 ..
-rw-r--r-- 1 march7th march7th  16736 Aug 13 05:25 defconfig
-rw-r--r-- 1 march7th march7th  13173 Aug 13 05:25 gki_defconfig
-rw-r--r-- 1 march7th march7th 182835 Aug 13 06:22 nethunter_defconfig
-rw-r--r-- 1 march7th march7th 168683 Aug 13 05:25 op8-perf_defconfig
-rw-r--r-- 1 march7th march7th   7579 Aug 13 05:25 ranchu64_defconfig
drwxr-xr-x 1 march7th march7th    468 Aug 13 05:25 vendor

可以看到,有一个 op8-perf_defconfig。我们的示例手机是一加8T。所以这就是我们要找的默认配置。

Help

如果arch/arm64/configs下没有你要的配置,不妨进入vendor文件夹一看。

使用文本编辑器打开该文件。在文件底部添加:

CONFIG_NAMESPACES=y
CONFIG_NET_NS=y
CONFIG_PID_NS=y
CONFIG_IPC_NS=y
CONFIG_UTS_NS=y
CONFIG_CGROUPS=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_SCHED=y
CONFIG_CPUSETS=y
CONFIG_MEMCG=y
CONFIG_KEYS=y
CONFIG_VETH=y
CONFIG_BRIDGE=y
CONFIG_BRIDGE_NETFILTER=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_MASQUERADE=y
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_IPVS=y
CONFIG_NETFILTER_XT_MARK=y
CONFIG_IP_NF_NAT=y
CONFIG_NF_NAT=y
CONFIG_POSIX_MQUEUE=y
CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
CONFIG_NF_NAT_IPV4=y
CONFIG_NF_NAT_NEEDED=y
CONFIG_OVERLAY_FS=y

然后保存退出,回到源码目录,执行:

make CC=clang AR=llvm-ar NM=llvm-nm STRIP=llvm-strip OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump O=out op8-perf_defconfig

加载默认配置。

此时我们已经可以开始编译。不过你可能还想修改一下别的,所以我们执行:

make CC=clang AR=llvm-ar NM=llvm-nm STRIP=llvm-strip OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump O=out  menuconfig

比如我们还想修改内核名,那我们需要修改这一项: General setup -> Local version - append to kernel release 修改完后,直接 ”Esc“ 保存退出

然后我们开始编译,输入以下命令

make CC=clang AR=llvm-ar NM=llvm-nm STRIP=llvm-strip OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump O=out -j$(nproc)

nproc会输出你 CPU 的线程数,也就是这条命令会让你的系统火力全开。如果你不想让它火力全开,酌情把$(nproc)换成一个比你 CPU 的线程数小的数字。

然后便是等待。等他出现Ready字样时就说明你成功了。

新版内核(5.4 以上) [WIP]

结合此文档阅读本小节内容:构建内核

为什么没有 5.4 内核? 5.4 是 GKI 1.0 版本, 这东西非常阴间, 笔者研究了两三天也毫无进展, 去 xda 一看, 根本没有人单独发布内核。所以决定放弃捏

注: 谷歌 Pixel 手机除外, 因为谷歌给 Pixel 的内核提供了很阳间的一键编译脚本

新版内核与上面的旧版内核最大的差别就是: 内核本身是统一由谷歌提供的, 存储在boot分区, 设备厂商提供的驱动等全部被拆分进入vendor_bootvendor_dlkm分区中, 这意味着内核碎片化从此不复存在了。

而我们, 再也不用东奔西走去找内核源码, 也不需要盼望厂商开源了. 开个香槟先🍾

如果你的设备出厂就是安卓12或更高版本, 那它就使用了这里的“新版内核”。

首先, 我们需要下载安卓的源码管理工具repo

以 Ubuntu 为例:

sudo apt install repo
其他发行版可以在软件仓库中搜索, 或是用这些命令安装:

sudo curl https://storage.googleapis.com/git-repo-downloads/repo > /usr/bin/repo && \
chmod a+x /usr/bin/repo

首先你需要安装 Magisk, 然后读取你手机boot镜像内的信息。

执行下面的命令:

uname -a
su -c dd if=/dev/block/by-name/boot$(getprop ro.boot.slot_suffix) of=/sdcard/boot.img
su -c /data/adb/magisk/magiskboot unpack /sdcard/boot.img

第一条命令会输出你的内核版本, 看起来像这样:

Linux localhost 4.19.268-march7th-ksu #4 SMP PREEMPT Sun Aug 10 11:45:14 JST 1919 aarch64 Android

*不要问这个为什么是 4.19.268, 因为笔者没有新版内核的设备

*你的应该是 5.10.x 或 5.15.x, 否则你应该看上面的旧版内核部分!

第三条命令会输出很多boot镜像的信息, 而我们需要关注以下几条:

OS_VERSION      [13.0.0]
OS_PATCH_LEVEL  [2022-12]
KERNEL_FMT      [raw]

新建文件夹, 叫什么随意。

进入你新建的文件夹;

根据上面的设备信息, 这里要拉取不同的分支;

这里没法给出非常具体的应该拉哪个分支, 只能给出几个例子:

比如你是安卓12(OS_VERSION 为 12.x.y), 内核版本为5.10.x, 安全补丁日期是2022年10月(OS_PATCH_LEVEL 为 2022-10), 执行下面的命令:

repo init -u https://android.googlesource.com/kernel/manifest -b common-android12-5.10-2022-10

再比如你是安卓13(OS_VERSION 为 13.x.y), 内核版本为5.15.x, 安全补丁日期是2022年12月(OS_PATCH_LEVEL 为 2022-12), 执行下面的命令:

repo init -u https://android.googlesource.com/kernel/manifest -b common-android13-5.15-2022-12

上条命令执行完后, 继续执行 repo sync -j$(nproc)

Help

这些命令可能会花费一点时间, 耐心的等一会.

Help

如果花费时间实在太长, 你可能必须通过镜像站拉取源代码, 把上面命令中所有的android.googlesource.com替换成mirrors.tuna.tsinghua.edu.cn/git/AOSP/即可. 例如repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/kernel/manifest -b common-android13-5.15-2022-12

Help

如果提示无法连接到gerrit.googlesource.com, 请参照git-repo的帮助页面的更新一节。

剩下的会写的,别急 可以先参考Ylarod 的教程

打包并刷入内核

考虑到有些手机并没有可用的第三方 Recovery ,所以我们不使用 Anykernel3 ,而是通过修改boot镜像手动刷入。

终端输入以下命令下载工具:

curl https://forum.xda-developers.com/attachments/aik-linux-v3-8-all-tar-gz.5300923/ | tar xzvf -

然后我们需要从手机中提取 Boot 镜像,并将其传到电脑上的工具目录内。如何提取镜像在前面 Root 的环节已经提到。

接着:

./unpackimg.sh <Boot 镜像文件名>

工具目录下会出现一个split_img文件夹,其中的<Boot 镜像文件名>-kernel就是我们要替换的文件。

编译好的内核在源码目录out/arch/arm64/boot目录下。一般来说文件名带有Image字样,把它复制到这里,替换掉原来的文件。

然后:

./repackimg.sh

重新打包内核文件,然后刷入重启。你应该会看到内核变化了。大功告成。


最后更新: January 10, 2023 01:57:43
创建日期: August 19, 2022 11:27:51