我开发这个项目的主要目的就是为了缩减我编译内核时要等待的时间,我觉得使用效果还不错所以就添加了一些使用说明希望也能对其他人有用。
项目链接: https://github.com/donglisi/kerncc
以下复制自我的 README.md
研究 Linux 内核的 Kbuild 系统让我发现一件有趣的事,Linux 内核的 Makefile 有一个名为 parpare0 的规则,这个规则执行后就生成了编译绝大多数 c 语言源代码文件的所需的头文件,而且 Linux 内核的 Makefile 生成的编译器命令行参数非常容易用程序去解析,于是我开发了这个项目来缩短我编译内核的时间。
这个程序支持用 2 台机一起编译 Linux 内核,kerncc 是编译器的包装器,kernccd 是接收编译任务的守护进程。
原理:
1,一台机用来执行 make 正常构建内核,另一台机仅仅负责生成可重定向目标文件,源代码和.config 需要在两台机的相同目录各拷贝一份,通过网络传输编译器命令行以及回传编译结果。
2, 正常编译的那台机通过设置内核 Makefile 的参数 CC 来指定编译器为 kerncc ,还需要设置 KERNCC_IP 环境变量来指定 kernccd 的 ip 地址,kerncc 默认会将 PATH 中的名为 gcc 的文件作为编译器,设置环境变量 KERNCC_CC 可以指定 kerncc 所使用的编译器。
3, 内核的 Makefile 有一个名为 parpare0 的规则,这个规则生成一些必要的头文件,在另一台机上执行 make parpare0 后就可以开始接收编译任务,当.config 修改后需要重新执行这一步。
4, kerncc 解析传给编译器的参数,如果是编译 c 语言源代码源文件的命令就允许分发到另一台机去编译,否则直接 exec 调用本机的编译器,是否分发到远程取决于文件的大小和一个随机数,小于一定的大小就直接在本机编译(默认是小于 1000 ,通过设置 KERNCC_SIZE 环境变量可以修改这个值),随机数用来进行负载均衡(每个 kerncc 进程都会生成一个大小在 0 到 100 之间的随机数,默认是大于 50 就分发到远程编译,可以通过设置环境变量 KERNCC_BALANCE 来更改这个值)。
5, 另一台机编译成功后会把 gcc 生成的.o 文件(可重定向目标文件)和.d 文件(用来记录有那些依赖的头文件)回传到正常编译的那台机。
6, kerncc 如果遇到连接不上 kernccd 或在另一台机上遇到编译报错或等待编译结果的过程中 kernccd 被异常终止等异常情况,就会在正常编译的这台机上重新执行一下同样的命令。
特性:
1, 因为 make 的过程中会生成一些.h 和.c 文件,这些文件只存在于正常编译的那台机上,这些生成的 c 源代码文件和依赖这些文件的 c 源代码文件无法在另一台机上编译,kernccd 遇到编译报错的情况时会把编译报错的 c 源代码文件的路径打印出来,可以将 kernccd 的输出保存到正常编译的那台机的编译输出目录下的名为 files 的文件中,kerncc 会读取这个 files 文件,这样下次编译时如果匹配到就直接在本地编译,节省了分发到远程编译的时间。不过需要注意的是编译报错也有可能是其他原因引起的,比如 2 台机的源代码不同步或代码错误,需要人工来判断具体的报错的原因。
2, 支持交叉编译其他体系结构的内核,比如要为 aarch64 架构编译内核,只需要在 make 前加上 KERNCC_CC=/usr/bin/aarch64-linux-gnu-gcc 就可以,完整的命令行类似这样:
KERNCC_CC=/usr/bin/aarch64-linux-gnu-gcc make -j56 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- CC=kerncc O=build
3, 相较于 distcc 有非常好的资源利用率,distcc 是把预处理后的文件分发到远程去编译再回传编译结果,因为预处理后的文件的体积比较大,所耗费的网络和存储资源较高,性能较差,kerncc 在设置合理的 KERNCC_SIZE 和 KERNCC_BALANCE 以及 make -j 并行任务数的情况下,几乎可以榨干两台机的 cpu 。
演示:
https://www.youtube.com/watch?v=cUZPV_Kygwc
这个视频演示了用 2 台机一起编译可以用来启动我的台式机的内核的效果,develop 这台机用来执行 make ,处理器为 3700X ,desktop 这台机运行 kernccd ,处理器为 5600X ,这 2 台机一起编译耗时 2 分钟(如果只用 3700X 这台机编译的话耗时是 3 分钟)。
右上角的小窗口运行 kernccd ,输出的是遇到编译报错的源代码文件的路径,这个小窗口下面的小窗口运行着 nload ,用来监控编译过程中的网络流量。
右下角的 2 个小窗口是 sysstat 包中的 sar 命令的格式化过的输出,最左边一列的数值越高表明越多的 cpu 时间用在实际的编译任务上,最右边的一列数字越高表明越多的 cpu 时间被浪费在运行空闲任务上。
1
kkocdko 2022-09-22 13:21:57 +08:00 1
您是否在找:分布式编译
|
2
qemu32 OP @kkocdko 我试过 distcc ,效果不理想,感觉完全没有缩短编译的时间,我开发这个程序主要是因为我家里有 2 台台式机,编译时一台满载一台空闲有点可惜,这个程序只是简单的利用了 2 台机的算力一起编译,不是什么分布式系统。
|
3
BrettD 2022-09-22 13:40:40 +08:00 via iPhone 2
有没有试过 https://github.com/nelhage/llama ?
|
4
linglin0924 2022-09-22 21:34:14 +08:00
编译的内核,会有 redhat 系的 rpm 包和 debian 的 apt 包吗
|
5
qemu32 OP @linglin0924 支持打 rpm 包和 deb 包,只要内核本身支持的功能我这个项目都支持,因为 kerncc 遇到远程报错就会本地重新执行,可以保证和直接用 gcc 编译一样的效果。
|
6
julyclyde 2022-09-23 08:25:16 +08:00
@qemu32 如果 distcc 没有缩短的话应该研究一下为什么
重新发明轮子没什么意义啊,不还是把别人早已踩过的再踩一遍吗 |
7
qemu32 OP @julyclyde 我这个项目不到 600 行代码,distcc 的代码 2 万 3 千行,做这 2 件事所需要花费的时间完全不能比,而且原理都不一样, 我这个描述里已经讲了为什么我这个性能会更好。
|
8
spatxos 2022-09-23 13:37:09 +08:00
先 star 了再说
|
9
JohnBull 2022-10-05 23:06:02 +08:00
distcc 了解下
|