Android | 打开内核的ZONED相关选项踩坑记

作为一名小白,要打开区区两个内核配置相关的编译选项,成功编译,打开并进入模拟器,看起来是一件事,其实是三件事,每一件事都花费了不少时间,这篇文章尝试总结一些方法论。

打开内核相关的编译选项

要打开内核相关的编译选项,我们首先得知道它究竟使用到了哪一个,因为整个Android代码里面,为各种架构,各种版本设计的编译选项一抓一大把,改哪里,是第一个问题。

Android内核代码使用了bazel这个编译工具进行编译,我们先进入到根目录的BUILD.bazel:

//common/BUILD.bazel
21:load("//build/kernel/kleaf:common_kernels.bzl", "define_common_kernels", "define_db845c")

这里加载了一个common_kernels.bzl文件

//build/kernel/kleaf/common_kernels.bzl:49
_ARCH_CONFIGS = {
    "kernel_aarch64": {
        "arch": "arm64",
        "build_config": "build.config.gki.aarch64",
        "outs": aarch64_outs,
    },
    "kernel_aarch64_interceptor": {
        "arch": "arm64",
        "build_config": "build.config.gki.aarch64",
        "outs": aarch64_outs,
        "enable_interceptor": True,
    },
    "kernel_aarch64_debug": {
        "arch": "arm64",
        "build_config": "build.config.gki-debug.aarch64",
        "outs": aarch64_outs,
    },
    "kernel_x86_64": {
        "arch": "x86_64",
        "build_config": "build.config.gki.x86_64",
        "outs": x86_64_outs,
    },
    "kernel_x86_64_debug": {
        "arch": "x86_64",
        "build_config": "build.config.gki-debug.x86_64",
        "outs": x86_64_outs,
    },
}

可以发现,kernel_x86_64使用的build_config是

"build.config.gki.x86_64"

找到这个文件:

//common/build.config.gki.x86_64
. ${ROOT_DIR}/${KERNEL_DIR}/build.config.common
. ${ROOT_DIR}/${KERNEL_DIR}/build.config.x86_64
. ${ROOT_DIR}/${KERNEL_DIR}/build.config.gki


BUILD_SYSTEM_DLKM=1
MODULES_LIST=${ROOT_DIR}/${KERNEL_DIR}/android/gki_system_dlkm_modules


BUILD_GKI_ARTIFACTS=1
BUILD_GKI_BOOT_IMG_SIZE=67108864

实际上它由三个部分组成。其中build.config.gki中:

DEFCONFIG=gki_defconfig
POST_DEFCONFIG_CMDS="check_defconfig"


if [ -n "${GKI_BUILD_CONFIG_FRAGMENT}" ]; then
source ${GKI_BUILD_CONFIG_FRAGMENT}
fi

所以我们知道了DEFCONFIG使用的是gki_defconfig。找到对应文件:

common/arch/x86/configs/gki_defconfig
里面全部是CONFIG的一些定义

在文件末尾添加上(或者修改已经存在的)我们想要的编译配置:

CONFIG_BLK_DEV_ZONED=y
CONFIG_BLK_DEV_NULL_BLK=y

好,到这里,完成了第一步。修改配置。

编译内核

打开了两个编译选项后,发现并编不过,很匪夷所思。

outside_default.png

经过学长的寻找,最后发现,要在build.config.gki文件中,注释掉deconfig的检查的那一条语句:

//common/build.config.gki
DEFCONFIG=gki_defconfig
# POST_DEFCONFIG_CMDS="check_defconfig" 注释此行


if [ -n "${GKI_BUILD_CONFIG_FRAGMENT}" ]; then
source ${GKI_BUILD_CONFIG_FRAGMENT}
fi

取消检查后就能编过了。

运行模拟器

编译过后以为可以运行起来了,就直接尝试,发现并不能:

outside_default.png

会报disagree错误,这个问题比较经典,因为之前切换内核的时候也遇到了,怀疑是版本错误,最后找到了解决方案:

outside_default.png

应该是版本检查时CRC循环冗余检验不过,由于我们这些工作都还是在测试,考虑跳过这个检查,同样修改之前的内核配置文件,将CONFIG_MODVERSIONS这个选项注释掉不打开,确实解决了这个问题,然后出现下一个问题:

outside_default.png

发现有模块还是无法成功加载,我发现,有一个version magic 'xx' should be 'xx'报错,经过查询,发现这也是一个版本校验的情况,内核与模块之间的版本不同不允许加载。

由于内核模块是通过预编译的方式,放置在AOSP代码中,内核版本与模块版本确实可能产生冲突,考虑更新模块版本,首先找到模块放置地址:

对于我的架构和Android系统版本,预编译的模块存放于:
AOSP/kernel/prebuilts/common-modules/virtual-device/5.15/x86-64

outside_default.png

使用命令:

tools/bazel build //common-modules/virtual-device:virtual_device_x86_64_dist

编译内核模块。编译完成后在目录:

kernel_source/bazel-bin/common-modules/virtual-device/virtual_device_x86_64

outside_default.png

把这些内核模块全部替换掉原来的内核模块,重新编译AOSP后,以上错误解决。

但是出现新错误,模拟器启动过程不会卡死,但是就是起不来。

经过逐行对比日志,发现surfaceflinger服务起不来,这个服务是Android里面图形化相关的服务,由于我们只修改了内核模块,会不会是某个模块被漏掉了?于是重新比较了一下,发现确实有若干模块并不在更新后的ko列表中。比如virtio-gpu.ko模块,很有可能是这个原因。

但是这个模块在哪呢?找到和模块编译相关的bazel文件:

common-modules/virtual-device/BUILD.bazel

搜索 virtio-gpu:

_virt_common_ext_modules = [
    "goldfish_drivers/goldfish_address_space.ko",
    "goldfish_drivers/goldfish_pipe.ko",
    "goldfish_drivers/goldfish_sync.ko",
    "virtio_gpu/virtio-gpu.ko",
]

发现它被定义为一种ext_modules,找到我们执行的命令对应条目:

kernel_build(
    name = "virtual_device_x86_64",
    srcs = [":virtual_device_x86_64_common_sources"],
    outs = [],
    base_kernel = "//common:kernel_x86_64",
    build_config = "build.config.virtual_device.x86_64",
    module_outs = _virt_common_modules + [
        # keep sorted
        "test_meminit.ko",
        "test_stackinit.ko",
    ],
)

发现它确实没有编译ext_modules,那ext_modules该怎么编呢,我在这个文件中又发现了一个编译选项:

kernel_module(
    name = "virtual_device_x86_64_external_modules",
    srcs = [":virtual_device_x86_64_common_sources"],
    outs = _virt_common_ext_modules,
    kernel_build = ":virtual_device_x86_64",
)

所以,可以通过执行:

tools/bazel build //common-modules/virtual-device:virtual_device_x86_64_external_modules

来编译external_modules。

于是执行,编译完毕后,将

bazel-bin/common-modules/virtual-device/virtual_device_x86_64_external_modules

目录下的.ko文件移动到AOSP目录对应位置,然后重新编译AOSP。

终于成功启动模拟器:

outside_default.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值