2 常见任务
本章介绍 Yocto Project Linux 内核开发常见任务,包括准备主机和层、修改 配方、打补丁、配置内核、迭代开发、使用自己的源码以及集成树外模块。
备注
本章示例适用于 Yocto Project 2.4 及以后版本。
2 准备内核开发构建主机
开始前应确保主机已准备好使用 Yocto Project,设置方法见 “准备使用 Yocto Project”。
备注
请检出适当开发分支,或从具体标签创建本地分支,以获得所需项目版本。
推荐使用 devtool, 而非传统内核流程。下文介绍两者。
2 准备使用 devtool 开发
以下步骤得到一个干净内核镜像,为 “使用 devtool 修补内核” 做准备:
初始化环境: 按 准备使用 Yocto Project 准备可运行 devtool 的 Shell。
准备 local.conf: 默认 MACHINE 为 qemux86-64,适合 64 位 QEMU。 其他目标需修改 Build Directory 中的 build/conf/local.conf,本例目录为
bitbake-builds/build。开发内核还需将 kernel-modules 加入 MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS。 本例选择 qemux86,追加如下:
MACHINE = "qemux86" MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS += "kernel-modules"
创建补丁层: 用 create-layer 创建保存内核补丁的层:
$ cd bitbake-builds/build $ bitbake-layers create-layer ../layers/meta-mylayer NOTE: Starting bitbake server... Add your new layer with 'bitbake-layers add-layer ../layers/meta-mylayer' $
将层告知构建环境: 按创建提示,将其加入配置文件的 BBLAYERS:
$ cd bitbake-builds/build $ bitbake-layers add-layer ../../meta-mylayer NOTE: Starting bitbake server... $
构建干净镜像: 最后用 BitBake 构建初始镜像:
$ bitbake core-image-minimal Parsing recipes: 100% |##########################################| Time: 0:00:05 Parsing of 830 .bb files complete (0 cached, 830 parsed). 1299 targets, 47 skipped, 0 masked, 0 errors. WARNING: No packages to add, building image core-image-minimal unmodified Loading cache: 100% |############################################| Time: 0:00:00 Loaded 1299 entries from dependency cache. NOTE: Resolving any missing task queue dependencies Initializing tasks: 100% |#######################################| Time: 0:00:07 Checking sstate mirror object availability: 100% |###############| Time: 0:00:00 NOTE: Executing SetScene Tasks NOTE: Executing RunQueue Tasks NOTE: Tasks Summary: Attempted 2866 tasks of which 2604 didn't need to be rerun and all succeeded.
若面向真实硬件,可将镜像写入例如
/dev/sdd的 U 盘启动。Minnowboard 示例见 TipsAndTricks/KernelDevelopmentWithEsdk。
现在可以开始修改,后续见 “使用 devtool 修补内核”。
2 准备传统内核开发
传统流程准备步骤大致相同,但还需创建本地内核源码副本供编辑。以下完成后, 即可按 “使用传统内核开发流程修补内核” 修改源码。
初始化环境: 按 准备使用 Yocto Project 操作。
准备 local.conf: 默认 MACHINE 为 qemux86-64,适合 64 位 QEMU;否则 修改构建目录的 build/conf/local.conf,本例为
bitbake-builds/build。还需让 MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS 包含内核模块。 本例使用 qemux86,追加:
MACHINE = "qemux86" MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS += "kernel-modules"
创建补丁层: 创建保存补丁的层:
$ cd bitbake-builds/build $ bitbake-layers create-layer ../../meta-mylayer NOTE: Starting bitbake server... Add your new layer with 'bitbake-layers add-layer ../../meta-mylayer'
加入构建环境: 将层加入 build/conf/bblayers.conf 的 BBLAYERS:
$ cd bitbake-builds/build $ bitbake-layers add-layer ../../meta-mylayer NOTE: Starting bitbake server ... $
克隆内核 Git 仓库: 受支持仓库位于 https://git.yoctoproject.org/ 的 "Yocto Linux Kernel" 分组。
建议放在 Source Directory 外,并切换到
standard/base。 以下克隆 linux-yocto-4.12:$ cd ~ $ git clone https://git.yoctoproject.org/linux-yocto-4.12 --branch standard/base Cloning into 'linux-yocto-4.12'... remote: Counting objects: 6097195, done. remote: Compressing objects: 100% (901026/901026), done. remote: Total 6097195 (delta 5152604), reused 6096847 (delta 5152256) Receiving objects: 100% (6097195/6097195), 1.24 GiB | 7.81 MiB/s, done. Resolving deltas: 100% (5152604/5152604), done. Checking connectivity... done. Checking out files: 100% (59846/59846), done.
备注
linux-yocto-4.12 适用于 Yocto Project 2.4 及以后,不适用于更早版本。
克隆内核缓存仓库: 同样建议放在源码目录外,本例检出 yocto-4.12 分支:
$ cd ~ $ git clone https://git.yoctoproject.org/yocto-kernel-cache --branch yocto-4.12 Cloning into 'yocto-kernel-cache'... remote: Counting objects: 22639, done. remote: Compressing objects: 100% (9761/9761), done. remote: Total 22639 (delta 12400), reused 22586 (delta 12347) Receiving objects: 100% (22639/22639), 22.34 MiB | 6.27 MiB/s, done. Resolving deltas: 100% (12400/12400), done. Checking connectivity... done.
准备完成,后续见 “使用传统内核开发流程修补内核”。
2 创建和准备层
修改内核配方时,建议在自己的层中工作,保存 BitBake 追加文件、 自定义配方和补丁。背景见 “理解和创建层”。
备注
bitbake-layers create-layer 可简化创建,见
“创建自己的层”。
为帮助理解,下面不用工具,手动在主目录创建 mylayer:
创建结构: 执行:
$ mkdir -p meta-mylayer/conf meta-mylayer/recipes-kernel/linux/linux-yocto
conf 保存配置,recipes-kernel 保存追加文件及补丁。
创建层配置: 在
meta-mylayer/conf创建 layer.conf:# We have a conf and classes directory, add to BBPATH BBPATH .= ":${LAYERDIR}" # We have recipes-* directories, add to BBFILES BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ ${LAYERDIR}/recipes-*/*/*.bbappend" BBFILE_COLLECTIONS += "mylayer" BBFILE_PATTERN_mylayer = "^${LAYERDIR}/" BBFILE_PRIORITY_mylayer = "5"
注意最后三条语句中的 mylayer。
创建内核追加文件: 在
meta-mylayer/recipes-kernel/linux创建linux-yocto_4.12.bbappend,本例使用 linux-yocto-4.12:FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" SRC_URI += "file://patch-file-one.patch" SRC_URI += "file://patch-file-two.patch" SRC_URI += "file://patch-file-three.patch"
FILESEXTRAPATHS 和 SRC_URI 使系统找到补丁。追加文件详见 “通过自己的层追加其他层元数据”。
2 修改已有配方
通常可定制已有 linux-yocto 配方。每个发行版提供几种选择,位于
OpenEmbedded-Core (OE-Core) 的 meta/recipes-kernel/linux。
修改包括:
先准备最小自定义层,见 “创建和准备层”。
2 创建追加文件
在自己的层中创建,与原配方对应命名。例如修改 linux-yocto_6.1.bb 时:
your-layer/recipes-kernel/linux/linux-yocto_6.1.bbappend
首先通过前置 FILESEXTRAPATHS 扩展 FILESPATH:
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
本例 ${THISDIR}/${PN} 展开为当前目录
下的 linux-yocto。新增文件应放在:
your-layer/recipes-kernel/linux/linux-yocto/
备注
新机器 BSP 开发还应参阅 Yocto Project 板级支持包(BSP)手册。
例如,meta-yocto-bsp 使用的追加文件:
meta-yocto-bsp/recipes-kernel/linux/linux-yocto_6.1.bbappend
其内容如下,示例提交 ID 可能与上游实际内容不同:
KBRANCH:genericx86 = "v6.1/standard/base"
KBRANCH:genericx86-64 = "v6.1/standard/base"
KBRANCH:beaglebone-yocto = "v6.1/standard/beaglebone"
KMACHINE:genericx86 ?= "common-pc"
KMACHINE:genericx86-64 ?= "common-pc-64"
KMACHINE:beaglebone-yocto ?= "beaglebone"
SRCREV_machine:genericx86 ?= "6ec439b4b456ce929c4c07fe457b5d6a4b468e86"
SRCREV_machine:genericx86-64 ?= "6ec439b4b456ce929c4c07fe457b5d6a4b468e86"
SRCREV_machine:beaglebone-yocto ?= "423e1996694b61fbfc8ec3bf062fc6461d64fde1"
COMPATIBLE_MACHINE:genericx86 = "genericx86"
COMPATIBLE_MACHINE:genericx86-64 = "genericx86-64"
COMPATIBLE_MACHINE:beaglebone-yocto = "beaglebone-yocto"
LINUX_VERSION:genericx86 = "6.1.30"
LINUX_VERSION:genericx86-64 = "6.1.30"
LINUX_VERSION:beaglebone-yocto = "6.1.20"
此文件支持多个随项目发布的 BSP,用 COMPATIBLE_MACHINE 定义机器, 以 KMACHINE 将构建系统机器名映射到内核机器名,并可用 KBRANCH 确保使用适当分支。
虽然本例没用,也可通过 KERNEL_FEATURES 启用内核专用功能。具体提交 指定构建 BSP 所需的精确内核。
该示例缺少开发 BSP 通常需要的内核配置。可以把完整配置或一组片段放在与 追加文件同级、名称与内核主配方相同的目录中,再通过 SRC_URI 引用。
例如,linux-yocto 目录中的 network_configs.cfg 可如此加入:
SRC_URI += "file://network_configs.cfg"
也可将以太网、图形等分组到各自文件:
SRC_URI += "file://myconfig.cfg \
file://eth.cfg \
file://gfx.cfg"
FILESEXTRAPATHS 用于扩展处理配方时查找文件和补丁的位置。
备注
还有其他组织方式。例如使用本地内核仓库时,可以检出 meta 分支,修改后 推送到本地裸仓库,直接为 BSP 增加配置。BSP 若最终加入项目,配置通常也 会进入该位置。
一般由维护者把 SRC_URI 中的配置移到 meta 分支。这样既减轻 BSP 开发者 负担,也可利用维护者的全局视角,将多个 BSP 的公共配置提升为公共功能。
2 应用补丁
单个或小系列补丁的处理与其他配方相同:复制到追加文件 FILESEXTRAPATHS 指定位置,再列入 SRC_URI。例如三补丁系列:
SRC_URI += "file://0001-first-change.patch"
SRC_URI += "file://0002-second-change.patch"
SRC_URI += "file://0003-third-change.patch"
下次 BitBake 构建时检测配方变化,先获取并应用补丁,再构建内核。
详细示例见 “使用 devtool 修补内核” 和 “使用传统内核开发流程修补内核”。
2 修改配置
可通过 defconfig 及 SRC_URI 中的配置片段,对最终 .config 作整体或增量修改。
已有完整可用 .config 时,复制到层的 recipes-kernel/linux 下对应 ${PN}
目录,命名为 defconfig,再在追加文件添加:
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://defconfig"
SRC_URI 指定文件,FILESEXTRAPATHS 扩展搜索目录。
也可使用 do_savedefconfig 生成、仅含非默认值的 defconfig, 但需额外设置 KCONFIG_MODE:
KCONFIG_MODE = "alldefconfig"
备注
系统先应用 defconfig,再应用所有配置片段,最终结果是两者组合,片段 覆盖在基础配置之上。
一般更推荐只描述所需增量。例如,为基本串口控制台创建 8250.cfg,内容如下, 不要缩进:
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
追加文件中引入并扩展搜索路径:
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://8250.cfg"
下次构建会获取并应用新配置。详细示例见 “配置内核”。
2 使用树内 defconfig 文件
有时希望使用内核源码树中该机器的 defconfig,同时保留片段支持。默认系统从 元数据层查找树外文件,并如下配置:
SRC_URI += "file://defconfig"
若不想在层中维护副本,可以使用树内默认配置,仍通过追加文件的 SRC_URI 添加片段。指定方式为:
KBUILD_DEFCONFIG:<machine> ?= "defconfig_file"
以下对基于 Broadcom 2708/2709 的 Raspberry Pi 2 使用机器覆盖设置 KBUILD_DEFCONFIG:
KBUILD_DEFCONFIG:raspberrypi2 ?= "bcm2709_defconfig"
若同时存在树外 defconfig 设置,KBUILD_DEFCONFIG 优先。详情见该变量文档。
2 使用 devtool 修补内核
以下流程展示 devtool 内核修补。
备注
先完成 “准备使用 devtool 开发”。
内核修补可涉及配置、支持硬件的配方,或源码本身。本例继续前述准备流程, 在 calibrate.c 添加 printk,让 QEMU 启动时输出新消息。
检出源码: 先让 devtool 在工作区检出内核。
备注
参阅 “准备使用 devtool 开发”。
运行:
$ devtool modify linux-yocto
编辑源码:
切换目录: 上一步输出源码位置,例如
build/workspace/sources/linux-yocto。编辑前进入该位置:$ cd build/workspace/sources/linux-yocto
修改文件: 将 init/calibrate.c 改为:
void calibrate_delay(void) { unsigned long lpj; static bool printed; int this_cpu = smp_processor_id(); printk("*************************************\n"); printk("* *\n"); printk("* HELLO YOCTO KERNEL *\n"); printk("* *\n"); printk("*************************************\n"); if (per_cpu(cpu_loops_per_jiffy, this_cpu)) { . . .
构建更新后的内核: 运行:
$ devtool build linux-yocto
生成包含新内核的镜像: 运行:
$ cd ~ $ devtool build-image core-image-minimal
备注
原镜像为 Wic 时也可采用替代方法,见 TipsAndTricks/KernelDevelopmentWithEsdk。
测试新镜像: 用 QEMU 验证。
启动: 执行:
$ runqemu qemux86
检查: 以 root 空密码登录,查看启动输出:
# dmesg | less
向下滚动应看到 printk 新消息。
暂存并提交: 回到修改 calibrate.c 的目录:
$ cd build/workspace/sources/linux-yocto $ git status $ git add init/calibrate.c $ git commit -m "calibrate: Add printk example"
导出补丁并创建追加文件: 使用先前的 meta-mylayer:
$ devtool finish linux-yocto ~/meta-mylayer
备注
建层方法见 “准备使用 devtool 开发” 第三步。
完成后,补丁和追加文件位于
~/meta-mylayer/recipes-kernel/linux。构建包含修改的镜像: 在已初始化的终端进入构建目录并运行:
$ cd bitbake-builds/build $ bitbake core-image-minimal
2 使用传统内核开发流程修补内核
以下不使用 devtool,作为 “使用 devtool 修补内核” 的另一方案。
备注
先完成 “准备传统内核开发”。
修补可以修改配置、配方或源码。本例同样在 calibrate.c 添加 printk,以 QEMU 启动输出验证,延续传统开发准备流程。
编辑源码: 假定已按前文克隆本地仓库。
切换目录: 在修改 calibrate.c 前进入内核仓库:
$ cd ~/linux-yocto-4.12/init
编辑文件: 修改为:
void calibrate_delay(void) { unsigned long lpj; static bool printed; int this_cpu = smp_processor_id(); printk("*************************************\n"); printk("* *\n"); printk("* HELLO YOCTO KERNEL *\n"); printk("* *\n"); printk("*************************************\n"); if (per_cpu(cpu_loops_per_jiffy, this_cpu)) { . . .
暂存并提交: 使用 Git:
$ git add calibrate.c $ git commit -m "calibrate.c - Added some printk statements"
未提交的修改不会被构建系统获取。
更新 local.conf 指向源码: 除 kernel-modules 和 qemux86 外,还需通过 SRC_URI 和 SRCREV 指向更新后的仓库:
$ cd bitbake-builds/build/conf
继续添加:
SRC_URI:pn-linux-yocto = "git:///path-to/linux-yocto-4.12;protocol=file;name=machine;branch=standard/base; \ git:///path-to/yocto-kernel-cache;protocol=file;type=kmeta;name=meta;branch=yocto-4.12;destsuffix=${KMETA}" SRCREV_meta:qemux86 = "${AUTOREV}" SRCREV_machine:qemux86 = "${AUTOREV}"
备注
将 path-to 替换为本地仓库路径,确认分支和机器正确。本例分别为 standard/base 和 qemux86。
构建镜像: 修改已提交且配置已指向源码后:
$ cd bitbake-builds/build $ bitbake core-image-minimal
启动镜像: QEMU 中用 root 空密码登录:
$ cd bitbake-builds/build $ runqemu qemux86
检查变化: 启动时消息可能快速滚过,可用以下命令查看:
# dmesg | less
应能看到 printk 输出。
生成补丁: 验证正确后,在内核仓库生成 patch:
$ cd ~/linux-yocto-4.12/init $ git format-patch -1 0001-calibrate.c-Added-some-printk-statements.patch
移动到层: 为后续构建使用,将补丁移到主目录下先前创建的 meta-mylayer。 yocto-create 当时未生成补丁目录结构,先添加:
$ cd ~/meta-mylayer $ mkdir -p recipes-kernel recipes-kernel/linux/linux-yocto
再移动文件:
$ mv ~/linux-yocto-4.12/init/0001-calibrate.c-Added-some-printk-statements.patch ~/meta-mylayer/recipes-kernel/linux/linux-yocto
创建追加文件: 在层的 recipes-kernel/linux 创建 linux-yocto_4.12.bbappend,内容如下:
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" SRC_URI += "file://0001-calibrate.c-Added-some-printk-statements.patch"
FILESEXTRAPATHS 和 SRC_URI 使构建系统找到补丁。更多信息见 “创建追加文件”、 “应用补丁” 和 “通过自己的层追加其他层元数据”。
备注
要再次构建 core-image-minimal 并检查补丁,可通过以下序列消除
bitbake-builds/build/tmp/work/...临时源码及之前构建的残留影响:$ cd bitbake-builds/build $ bitbake -c cleanall linux-yocto $ bitbake core-image-minimal -c cleanall $ bitbake core-image-minimal $ runqemu qemux86
2 配置内核
内核配置要确保 .config 包含镜像所需的全部正确设置。可使用 menuconfig 和 配置片段,也可将已知配置保存为 defconfig。本节介绍交互配置、片段及配置 精简,另见 “修改配置”。
2 创建 defconfig 文件
Yocto Project 中的 defconfig 通常是从构建复制的 .config,或从内核树移到 配方空间的 defconfig,保存已知配置,供系统生成最终 .config。
备注
项目默认不附带 defconfig 或 .config,最终配置由构建系统生成。
从完整可用 .config 开始,复制到层 recipes-kernel/linux 下对应
${PN} 目录并命名 defconfig,例如
~/meta-mylayer/recipes-kernel/linux/linux-yocto/defconfig。追加文件中设置:
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://defconfig"
SRC_URI 引用文件,FILESEXTRAPATHS 将目录加入 FILESPATH。
备注
系统先应用 defconfig,再将所有片段叠加其上,最终配置是两者组合。
更多信息见 “修改配置”。
2 创建配置片段
配置片段是放在系统可找到位置的一组内核选项,语法与构建目录 .config 相同。 它在 defconfig 之后应用,可以覆盖基础配置。
备注
.config 位置示例见 “使用 menuconfig”。
创建很简单,例如用 Shell 生成 my_changes.cfg,启用多处理器支持并禁用 FPGA 配置框架:
$ echo "CONFIG_SMP=y" >> my_changes.cfg
$ echo "# CONFIG_FPGA is not set" >> my_changes.cfg
备注
所有片段必须使用 .cfg 扩展名,构建系统才会识别。
也可比较原配置与 menuconfig 新配置:
完成内核配置任务: 至少构建至配置阶段:
$ bitbake linux-yocto -c kernel_configme -f
这样从已知状态生成 .config。构建状态可能不明确,因此最好在 menuconfig 前运行该任务。
启动 menuconfig: 执行:
$ bitbake linux-yocto -c menuconfig
生成片段: diffconfig 将 fragment.cfg 放入
${WORKDIR}:$ bitbake linux-yocto -c diffconfig
生成文件是一组 CONFIG_ 赋值,使用方法见
“修改配置”。
备注
也可用于 BSP,见 “BSP 描述”。
片段应放在层内 SRC_URI 指向的可搜索位置,构建系统会将其加入内核配置。 例如,把 myconfig.cfg 放在追加文件同级的 linux-yocto 目录,再添加:
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://myconfig.cfg"
相关配置可拆为多文件,例如以太网和图形:
SRC_URI += "file://myconfig.cfg \
file://eth.cfg \
file://gfx.cfg"
2 验证配置
$ bitbake linux-yocto -c kernel_configcheck -f
请求选项未进入最终 .config,或硬件片段覆盖策略配置时会警告。运行前必须已有 .config,创建方式见 “使用 menuconfig”。
示例输出:
Loading cache: 100% |########################################################| Time: 0:00:00
Loaded 1275 entries from dependency cache.
NOTE: Resolving any missing task queue dependencies
Build Configuration:
.
.
.
NOTE: Executing SetScene Tasks
NOTE: Executing RunQueue Tasks
WARNING: linux-yocto-4.12.12+gitAUTOINC+eda4d18ce4_16de014967-r0 do_kernel_configcheck:
[kernel config]: specified values did not make it into the kernel's final configuration:
---------- CONFIG_X86_TSC -----------------
Config: CONFIG_X86_TSC
From: /home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/bsp/common-pc/common-pc-cpu.cfg
Requested value: CONFIG_X86_TSC=y
Actual value:
---------- CONFIG_X86_BIGSMP -----------------
Config: CONFIG_X86_BIGSMP
From: /home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/cfg/smp.cfg
/home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/defconfig
Requested value: # CONFIG_X86_BIGSMP is not set
Actual value:
---------- CONFIG_NR_CPUS -----------------
Config: CONFIG_NR_CPUS
From: /home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/cfg/smp.cfg
/home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/bsp/common-pc/common-pc.cfg
/home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/defconfig
Requested value: CONFIG_NR_CPUS=8
Actual value: CONFIG_NR_CPUS=1
---------- CONFIG_SCHED_SMT -----------------
Config: CONFIG_SCHED_SMT
From: /home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/cfg/smp.cfg
/home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/defconfig
Requested value: CONFIG_SCHED_SMT=y
Actual value:
NOTE: Tasks Summary: Attempted 288 tasks of which 285 didn't need to be rerun and all succeeded.
Summary: There were 3 WARNING messages shown.
备注
示例输出为便于阅读人为折行。
日志描述问题及相关配置位置。根据日志调整,再反复运行 do_kernel_configme 和 do_kernel_configcheck, 直至无警告。menuconfig 用法见 使用 menuconfig。
2 精简内核配置文件
反复阅读片段审计结果、修改问题,可使 .config 尽可能精简有效。
构建中的 kernel_configcheck 将最终配置与输入比较,报告:
请求但未进入最终配置的选项。
同一片段中重复的项目。
标记为 required 却被覆盖的项目。
开发板覆盖非板专用选项。
当前内核中根本不存在的无效选项。
备注
还可选报告处理过程中任何被覆盖的选项。
每个警告指向选项列表文件及定义它们的片段,这些文件是精简配置的关键。
流程如下:
使用已知可用配置: 确认完整配置能够构建并启动,作为基线。
分别运行配置与检查任务:
分别执行:
$ bitbake linux-yocto -c kernel_configme -f $ bitbake linux-yocto -c kernel_configcheck -f
处理结果: 根据警告文件:
删除片段中重复定义、但不影响最终配置的值。
分析并酌情删除覆盖必需配置的值。
分析并酌情删除非开发板专用选项。
删除重复和无效项。
重新配置并检查: 再运行两个任务,检查效果并处理剩余问题。
迭代第二至第四步,最终得到精简配置,然后构建 Linux Yocto 内核。
2 展开变量
可用 bitbake-getvar 查看构建中变量的展开结果:
$ bitbake-getvar -r virtual/kernel VARIABLE
输出详细说明 OpenEmbedded Build System 如何展开并使用变量。
2 处理带 “Dirty” 的内核版本字符串
版本字符串以 "+" 或 "-dirty" 结尾,表示源码目录有未提交修改。清理步骤:
查找修改: 在本地内核 Git 仓库列出修改、添加或删除的文件:
$ git status
提交: 无论最终是否保存、导出或使用,都应提交这些修改:
$ git add $ git commit -s -a -m "getting rid of -dirty"
重建内核: 命令因流程而异。devtool 方法见 “使用 devtool 修补内核”, BitBake 方法见 “使用传统内核开发流程修补内核”。
2 使用自己的源码
如果无法采用已有 linux-yocto 配方支持的内核版本,仍可用自己的源码配合 Yocto 内核工具。虽然不能直接利用现有元数据和稳定化成果,仍可使用相同格式 管理自己的元数据,便于未来在共同支持的版本上与 linux-yocto 汇合。
项目提供使用 kernel.org 源码和内核工具的 自定义配方。
基本步骤:
复制配方: 将 linux-yocto-custom.bb 放入自己的层,合理命名并包含 基线内核版本,例如 linux-yocto-myproject_4.12.bb。
创建补丁目录: 同目录建立 linux-yocto-myproject 等对应目录,保存 补丁和配置。
准备配置: 必须提供 defconfig 或配置片段。没有 defconfig 时,可运行:
$ make defconfig
将生成的 .config 复制到层的 files 目录,命名 defconfig,并加入 SRC_URI。
make defconfig 生成内核为该架构定义的默认配置,但不保证满足用途或能 启动开发板,非 x86 尤其如此。应查找最接近开发板的配置,例如 ARM 的 arch/arm/configs。
编辑配方: 按项目修改:
SRC_URI:通过 file、git、http 等受支持协议指定 Git 仓库, 并列出 defconfig 或片段。骨架中有语法示例。
LINUX_VERSION:使用的内核版本,如 4.12。
LINUX_VERSION_EXTENSION:编入内核的 CONFIG_LOCALVERSION, 可通过 uname 查看。
SRCREV:构建所用提交 ID。
PR:与普通配方相同,通过递增表示配方变化。
COMPATIBLE_MACHINE:支持的机器。示例默认 "(^$)" 只匹配空串, 刻意使构建失败,必须更改。例如支持 qemux86 和 qemux86-64:
COMPATIBLE_MACHINE = "qemux86|qemux86-64"
按需继续定制: 与修改已有配方相同,见 “修改现有配方”。
2 使用树外模块
本节介绍在目标构建树外模块,以及将模块集成到构建中。
2 在目标上构建树外模块
传统方式是在正常构建中包含模块,但目标性能足够时,本机编译也可能有用。 不过应先考虑从构建主机使用正确交叉开发环境的优势。
运行 SDK 镜像的目标需要先做准备。所有 *.sdk 镜像默认安装 kernel-dev,
许多还安装 kernel-devsrc,但编译树外模块前仍需生成脚本。
以 root 登录,进入 /usr/src/kernel 并生成脚本:
# cd /usr/src/kernel
# make scripts
所有 SDK 镜像包含 dev-pkgs,因此安装 kernel-dev,适用镜像还安装 devsrc。 SDK 用这些脚本构建模块,准备完成后即可在目标编译。
2 集成树外模块
最好将代码集成进内核,但确需外部模块时,可用 hello-mod 作模板。
复制到层并命名,例如 mymodule_1.0.bb。同目录创建 files,保存源码未包含的 文件和补丁,再按需更新。通常需设置:
根据模块构建系统可能还需调整。典型 Makefile 如下:
obj-m := hello.o
SRC := $(shell pwd)
all:
$(MAKE) -C $(KERNEL_SRC) M=$(SRC)
modules_install:
$(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install
...
关键是 KERNEL_SRC。module 将它和
KERNEL_PATH 设为 ${STAGING_KERNEL_DIR},提供所需内核构建信息。
若模块使用不同变量,可覆盖编译任务或修补 Makefile 采用这些常见变量。
准备好配方后,在机器配置中适当设置下列变量之一以加入镜像:
模块通常不是启动必需,可在某些配置中排除,最灵活的方式是:
MACHINE_EXTRA_RRECOMMENDS += "kernel-module-mymodule"
值由 kernel-module- 加不带 .ko 的模块文件名构成。因为是 RRECOMMENDS 而非 RDEPENDS,模块不可用时不会导致构建失败。
2 检查变更和提交
要了解内核树应用了哪些修改,Git 比跨目录 grep 更高效。
2 内核发生了什么变化?
以下仅是若干 Git 检查方式,并非全部。
备注
不指定提交范围时,kernel.org 历史与 Yocto 修改混合。可以用分支名作为 上下界,仓库界面 https://git.yoctoproject.org/ 可查看分支。
用 git whatchanged 和 commit..commit 查看范围内变化。
例如,linux-yocto-3.19 的 emenlow 分支,以 standard/base 为下界、
standard/emenlow 为上界:
$ git whatchanged origin/standard/base..origin/standard/emenlow
单行摘要:
$ git log --oneline origin/standard/base..origin/standard/emenlow
代码差异:
$ git diff origin/standard/base..origin/standard/emenlow
提交说明和文本差异:
$ git show origin/standard/base..origin/standard/emenlow
为每项变更生成单独补丁,并放到 Documents:
$ git format-patch -o $HOME/Documents origin/standard/base..origin/standard/emenlow
2 显示特定功能或分支变化
标签划分重要功能或分支变更。git show tag 可显示,例如 systemtap:
$ git show systemtap
git branch --contains tag 显示包含该功能的分支:
$ git branch --contains systemtap
2 添加配方空间内核功能
在 配方空间 中,可以用 KERNEL_FEATURES 并在 SRC_URI 指定 SCC 路径添加功能。系统会检查功能 是否存在,缺失则停止构建。功能最后参与配置和补丁处理,因此这样可以强制 确保某功能存在且启用,无需全面审计其他层对 SRC_URI 的添加。
KERNEL_FEATURES 中的 SCC 路径相对于内核元数据根目录。系统搜索 SRC_URI 提供的所有元数据,无论来自 kernel-cache、系统元数据还是配方空间,详见 “内核元数据位置”。
SRC_URI 指定 SCC 后,其所在目录和全部子目录都加入功能搜索路径,因此 一个条目可以暴露多个功能。
以下添加 test.scc:
创建功能文件: 像补丁、cfg 或其他获取项一样放置 SCC。
备注
与补丁一样,将所在目录加入获取器搜索路径。
可在该目录下建立其他 SCC,所有子目录都会作为潜在功能目录搜索。
例如位置为:
my_recipe | +-linux-yocto | +-test.cfg +-test.scc
linux-yocto 中同时有 test.scc 和对应 test.cfg。
加入 SRC_URI: 添加:
SRC_URI += "file://test.scc"
路径前的空格很重要,因为内容追加到已有值。
声明为内核功能: 设置:
KERNEL_FEATURES += "test.scc"
构建内核时就会处理该功能。
备注
test.scc 下面的其他功能,其目录相对于 test.scc 所在位置。