Linux绕过内核缓存,在Linux中内核构建缓存/非确定性

我运行一个CI服务器,用于构建自定义

Linux内核. CI服务器功能不强,每个构建的时间限制为3h.为了在这个限制内工作,我有了使用ccache缓存内核构建的想法.我希望我可以在每个次要版本发布时创建一个缓存,并将其重新用于补丁版本,例如:我有一个我为4.18制作的缓存,我想用于所有4.18.x内核.

删除构建时间戳后,这适用于我正在构建的确切内核版本.对于上面引用的4.18内核,在CI上构建它会提供以下统计信息:

$ccache -s

cache directory

primary config

secondary config (readonly) /etc/ccache.conf

stats zero time Thu Aug 16 14:36:22 2018

cache hit (direct) 17812

cache hit (preprocessed) 38

cache miss 0

cache hit rate 100.00 %

called for link 3

called for preprocessing 29039

unsupported code directive 4

no input file 2207

cleanups performed 0

files in cache 53652

cache size 1.4 GB

max cache size 5.0 GB

缓存命中率100%和一小时完成构建,梦幻般的统计数据和预期.

不幸的是,当我尝试构建4.18.1时,我得到了

cache directory

primary config

secondary config (readonly) /etc/ccache.conf

stats zero time Thu Aug 16 10:36:22 2018

cache hit (direct) 0

cache hit (preprocessed) 233

cache miss 17658

cache hit rate 1.30 %

called for link 3

called for preprocessing 29039

unsupported code directive 4

no input file 2207

cleanups performed 0

files in cache 90418

cache size 2.4 GB

max cache size 5.0 GB

这是1.30%的命中率,而构建时间反映了这种糟糕的表现.从仅一个补丁版本改变.

我原本预计缓存性能会随着时间的推移而降低,但不会达到这种程度,所以我唯一的想法就是有更多的非确定性而不仅仅是时间戳.例如,大多数/所有源文件是否包括完整的内核版本字符串?我的理解是,像这样的东西会彻底打破缓存.有没有办法让缓存按照我的意愿工作或者不可能?

有include / generated / uapi / Linux / version.h头文件(在顶级Makefile

https://elixir.bootlin.com/Linux/v4.16.18/source/Makefile中生成)

其中包括精确的内核版本作为宏:

version_h := include/generated/uapi/Linux/version.h

old_version_h := include/Linux/version.h

define filechk_version.h

(echo \#define Linux_VERSION_CODE $(shell \

expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \

echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)

endef

$(version_h): $(srctree)/Makefile FORCE

$(call filechk,version.h)

$(Q)rm -f $(old_version_h)

因此,将生成用于Linux 4.16.18的version.h(266258是(4<<< 16)(16<<<< 8)18 = 0x41012)

#define Linux_VERSION_CODE 266258

#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))

稍后,例如在模块构建中,应该有方法来读取Linux_VERSION_CODE宏值https://www.tldp.org/LDP/lkmpg/2.4/html/lkmpg.html(4.1.6.为多个内核版本编写模块)

The way to do this to compare the macro Linux_VERSION_CODE to the macro KERNEL_VERSION. In version a.b.c of the kernel, the value of this macro would be 2^{16}a+2^{8}b+c. Be aware that this macro is not defined for kernel 2.0.35 and earlier, so if you want to write modules that support really old kernels

如何包含version.h?示例模块包括< Linux / kernel.h> < Linux /&module.h中GT;和< Linux / modversions.h>,其中一个文件可能间接包含全局version.h.大多数甚至所有内核源代码都包含version.h.

比较构建时间戳时,可能会重新生成version.h并禁用ccache.当忽略时间戳时,Linux_VERSION_CODE仅对完全相同的Linux内核版本相同,并且对于下一个补丁级别进行更改.

更新:检查一些内核对象编译的gcc -H输出,会有另一个带有完整内核版本宏定义的头.例如:include / generated / utsrelease.h(UTS_RELEASE宏),include / generated / autoconf.h(CONFIG_VERSION_SIGNATURE).

或者甚至在两个补丁级别之间进行相同内核对象编译的gcc -E预处理,并比较生成的文本.使用最简单的Linux模块,我直接在gcc命令行中包含./include/Linux/kconfig.h,它包含include / generated / autoconf.h(但这在-H输出中不可见,是bug还是功能GCC?).

https://patchwork.kernel.org/patch/9326051/

… because the top Makefile forces to include it with:

06002

它实际上是:https://elixir.bootlin.com/Linux/v4.16.18/source/Makefile

# Use USERINCLUDE when you must reference the UAPI directories only.

USERINCLUDE := \

-I$(srctree)/arch/$(SRCARCH)/include/uapi \

-I$(objtree)/arch/$(SRCARCH)/include/generated/uapi \

-I$(srctree)/include/uapi \

-I$(objtree)/include/generated/uapi \

-include $(srctree)/include/Linux/kconfig.h

# Use LinuxINCLUDE when you must reference the include/ directory.

# Needed to be compatible with the O= option

LinuxINCLUDE := \

-I$(srctree)/arch/$(SRCARCH)/include \

-I$(objtree)/arch/$(SRCARCH)/include/generated \

$(if $(KBUILD_SRC), -I$(srctree)/include) \

-I$(objtree)/include \

$(USERINCLUDE)

LinuxINCLUDE导出到env并在source / scripts / Makefile.lib中用于定义编译器标志https://elixir.bootlin.com/Linux/v4.16.18/source/scripts/Makefile.lib

c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LinuxINCLUDE)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值