openharmony5.0.0中kernel子系统编译构建流程概览(rk3568)

概述

在梳理openharmony对linux内核做了哪些更改时,简单梳理了下kernel部分的编译构建流程,并根据源码做了简单论证。分享出来,希望对大家有所帮助。

系统版本:openharmony5.0.0

开发板:dayu200

编译环境:ubuntu22

执行流程

在kernel\linux\build\目录可以梳理出内核代码的如下执行流程:

在这里插入图片描述

其中BUILD.gn为openharmony中gn+ninja的正常编译流程,调用过程不再跟踪。

BUILD.gn

由执行流程图可知BUILD.gn是通过如下命令进行build_kernel.sh脚本的调用的。

 action("build_kernel") {//定义一个构建任务,action参数用于定义构建过程中的具体操作script = "build_kernel.sh"//指定了用于构建内核的脚本文件为`build_kernel.sh`sources = [ kernel_source_dir ]//指定内核源码目录//kernel/linux/$linux_kernel_versiondeps = [ ":check_build" ]//在执行构建内核任务之前,必须先完成`:check_build`任务,check_build为上文定义的check_build.sh脚本product_path = "vendor/$product_company/$product_name"//产品自定义相关的目录build_type = "standard"//构建类型为标准构建outputs = [ "$root_build_dir/packages/phone/images/$kernel_image" ]//构建的最终输出文件的位置和名称args = [//列出了传递给构建脚本的参数rebase_path(kernel_build_script_dir, root_build_dir),//1.重新计算内核构建脚本目录相对于构建目录根路径的路径,kernel_build_script_dir = "//kernel/linux/build";,定位到out输出的目录rebase_path("$root_out_dir/../KERNEL_OBJ"),//2.重新计算内核对象文件目录相对于某个输出目录的路径rebase_path("$root_build_dir/packages/phone/images"),//3.重新计算内核镜像文件放置目录相对于构建目录根路径的路径build_type,//4.构建类型,这里已经定义为"standard"target_cpu,//5.目标CPU架构,构建内核时需要指定针对哪种CPU架构进行构建product_path,//6.产品路径,已在前面定义device_name,//7.设备名称,表示正在构建内核的具体设备型号linux_kernel_version,//8.Linux内核版本号,表示正在构建的内核的具体版本]}

build_kernel.sh

build_kernel.sh脚本主要进行了kernel_module_build.sh脚本的调用

pushd ${1} #进入编译目录即:
./kernel_module_build.sh ${2} ${4} ${5} ${6} ${7} ${8}
.....对编译文件的复制操作,此处省略

kernel_module_build.sh

此文件主要是将对应的变量做对应的赋值,下面将DAYU200开发板中的编译方法(./build.sh --product-name rk3568)配置选项按实际情况进行了注释

export OUT_DIR=$1 #out
export BUILD_TYPE=$2 #standard
export KERNEL_ARCH=$3 #arm64
export PRODUCT_PATH=$4 #vendor/hihope/rk3568
export DEVICE_NAME=$5 #rk3568
export KERNEL_VERSION=$6#linux-5.10
LINUX_KERNEL_OUT=${OUT_DIR}/kernel/src_tmp/${KERNEL_VERSION}
export OHOS_ROOT_PATH=$(pwd)/../../..
....
make -f kernel.mk

由上可见最终在执行make时使用-f参数指定了kernel.mk文件

kernel.mk

为了简化说明下面将DAYU200(rk3568)开发板相关的内容保留之后的makefile文件保留了,如下:

PRODUCT_NAME=$(TARGET_PRODUCT) #产品的名称,取自环境变量`TARGET_PRODUCT
OHOS_BUILD_HOME := $(realpath $(shell pwd)/../../../) #构建系统的主目录,通过`realpath`和`pwd`命令计算出绝对路径#
KERNEL_SRC_TMP_PATH := $(OUT_DIR)/kernel/${KERNEL_VERSION} #内核源代码的临时路径
KERNEL_OBJ_TMP_PATH := $(OUT_DIR)/kernel/OBJ/${KERNEL_VERSION} #内核编译对象的临时路径#如果`BUILD_TYPE`为`standard`,则设置`BOOT_IMAGE_PATH`和`KERNEL_SRC_TMP_PATH`,并导出`KERNEL_SRC_DIR`环境变量
ifeq ($(BUILD_TYPE), standard)BOOT_IMAGE_PATH = $(OHOS_BUILD_HOME)/device/board/hisilicon/hispark_taurus/uboot/prebuiltsKERNEL_SRC_TMP_PATH := $(OUT_DIR)/kernel/src_tmp/${KERNEL_VERSION}export KERNEL_SRC_DIR=out/KERNEL_OBJ/kernel/src_tmp/${KERNEL_VERSION}
endifKERNEL_SRC_PATH := $(OHOS_BUILD_HOME)/kernel/linux/${KERNEL_VERSION}#内核源代码的实际路径
KERNEL_PATCH_PATH := $(OHOS_BUILD_HOME)/kernel/linux/patches/${KERNEL_VERSION}#内核补丁文件的路径
KERNEL_CONFIG_PATH := $(OHOS_BUILD_HOME)/kernel/linux/config/${KERNEL_VERSION}#内核配置文件的路径
PREBUILTS_GCC_DIR := $(OHOS_BUILD_HOME)/prebuilts/gcc#预编译的GCC工具链路径
CLANG_HOST_TOOLCHAIN := $(OHOS_BUILD_HOME)/prebuilts/clang/ohos/linux-x86_64/llvm/bin#预编译的Clang工具链路径#
KERNEL_HOSTCC := $(CLANG_HOST_TOOLCHAIN)/clang #用于主机编译的工具链
KERNEL_PREBUILT_MAKE := make #使用的`make`工具
CLANG_CC := $(CLANG_HOST_TOOLCHAIN)/clang #交叉编译工具链的前缀,初始为空KERNEL_CROSS_COMPILE :=
......KERNEL_TARGET_TOOLCHAIN := $(PREBUILTS_GCC_DIR)/linux-x86/aarch64/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/binKERNEL_TARGET_TOOLCHAIN_PREFIX := $(KERNEL_TARGET_TOOLCHAIN)/aarch64-linux-gnu-#选择相应的交叉编译工具链和前缀
.....KERNEL_CROSS_COMPILE += CC="$(CLANG_CC)"
KERNEL_CROSS_COMPILE += CROSS_COMPILE="$(KERNEL_TARGET_TOOLCHAIN_PREFIX)"
KERNEL_MAKE := \PATH="$(BOOT_IMAGE_PATH):$$PATH" \$(KERNEL_PREBUILT_MAKE) #设置`PATH`环境变量并使用`make`命令DEVICE_PATCH_DIR := $(OHOS_BUILD_HOME)/kernel/linux/patches/${KERNEL_VERSION}/$(DEVICE_NAME)_patch
DEVICE_PATCH_FILE := $(DEVICE_PATCH_DIR)/$(DEVICE_NAME).patch
KERNEL_IMAGE_FILE := $(KERNEL_SRC_TMP_PATH)/arch/$(KERNEL_ARCH)/boot/$(KERNEL_IMAGE)#生成的内核镜像文件路径
DEFCONFIG_FILE := $(DEVICE_NAME)_$(BUILD_TYPE)_defconfig#内核配置文件名
UNIFIED_COLLECTION_PATCH_FILE := ${OHOS_BUILD_HOME}/kernel/linux/common_modules/ucollection/apply_ucollection.sh#统一集合补丁脚本路径#export KBUILD_OUTPUT=$(KERNEL_OBJ_TMP_PATH)#导出`KBUILD_OUTPUT`环境变量,指定内核编译输出路径$(KERNEL_IMAGE_FILE):$(hide) echo "build kernel..."
......$(hide) rm -rf $(KERNEL_SRC_TMP_PATH);mkdir -p $(KERNEL_SRC_TMP_PATH);cp -arfL $(KERNEL_SRC_PATH)/* $(KERNEL_SRC_TMP_PATH)/ # 复制源代码$(hide) $(OHOS_BUILD_HOME)/drivers/hdf_core/adapter/khdf/linux/patch_hdf.sh $(OHOS_BUILD_HOME) $(KERNEL_SRC_TMP_PATH) $(KERNEL_PATCH_PATH) $(DEVICE_NAME) # 调用`patch_hdf.sh`脚本,应用设备驱动框架相关的补丁
......$(hide) cd $(KERNEL_SRC_TMP_PATH) && test -f $(DEVICE_PATCH_FILE) && patch -p1 < $(DEVICE_PATCH_FILE) || true #根据产品路径或设备名称,应用特定的补丁文件ifeq ($(UNIFIED_COLLECTION_PATCH_FILE), $(wildcard $(UNIFIED_COLLECTION_PATCH_FILE)))#如果存在获取进程cpu维测数据的脚本(提升获取CPU使用率的效率的服务),则执行该脚本,此脚本通过创建符号链接,可以方便地将位于不同目录的源码文件链接到内核构建目录中,避免了复制文件的过程$(hide) $(UNIFIED_COLLECTION_PATCH_FILE) $(OHOS_BUILD_HOME) $(KERNEL_SRC_TMP_PATH) $(DEVICE_NAME) $(KERNEL_VERSION)
endif#复制内核配置文件到源代码临时路径。使用`make`命令进行清理、配置、模块准备和编译。$(hide) cp -rf $(KERNEL_CONFIG_PATH)/. $(KERNEL_SRC_TMP_PATH)/$(hide) $(KERNEL_MAKE) -C $(KERNEL_SRC_TMP_PATH) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) distclean #清理$(hide) $(KERNEL_MAKE) -C $(KERNEL_SRC_TMP_PATH) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(DEFCONFIG_FILE) #配置
ifeq ($(KERNEL_VERSION), linux-5.10)$(hide) $(KERNEL_MAKE) -C $(KERNEL_SRC_TMP_PATH) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) modules_prepare #模块准备
endif$(hide) $(KERNEL_MAKE) -C $(KERNEL_SRC_TMP_PATH) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) -j64 $(KERNEL_IMAGE)  #编译
....
#定义一个伪目标`build-kernel`,依赖于`$(KERNEL_IMAGE_FILE)`。
#当运行`make build-kernel`时,会触发内核镜像的构建。
.PHONY: build-kernel
build-kernel: $(KERNEL_IMAGE_FILE)

📑$(hide) 通常用于 make 文件中的命令前缀。它会将命令的输出重定向到 /dev/null,从而隐藏命令的输出。调试时可以在调用 make 时使用 -s 选项来禁用所有命令的输出隐藏。

通过对以上的分析,可总结出我们比较关注的信息如下:

合入HDF补丁(patch_hdf.sh)

在第47行中可见HDF的补丁合入方法,合入不同内核版本对应的HDF内核补丁:

$(hide) $(OHOS_BUILD_HOME)/drivers/hdf_core/adapter/khdf/linux/patch_hdf.sh $(OHOS_BUILD_HOME) $(KERNEL_SRC_TMP_PATH) $(KERNEL_PATCH_PATH) $(DEVICE_NAME)

patch_hdf.sh脚本四个参数含义为:第一个入参为工程根目录路径,第二入参为内核目录路径,第三个入参为内核版本路径,第四个参数是当前设备名

此文件主要执行将hdf相关的补丁(kernel\linux\pathces\linux-5.10\rk3568_patch\hdf.patch)打入到系统中,具体的操作可以直接参看源码中的脚本文件drivers\hdf_core\adapter\khdf\linux\patch_hdf.sh

特定补丁文件

/kernel/linux/patches/${KERNEL_VERSION}/$(DEVICE_NAME)_patch目录中合入特定补丁$(DEVICE_NAME).patch,

$(hide) cd $(KERNEL_SRC_TMP_PATH) && test -f $(DEVICE_PATCH_FILE) && patch -p1 < $(DEVICE_PATCH_FILE) || true 
  • $(hide) :这是 make 工具的一个特性,用于隐藏命令的输出。它会将命令的输出重定向到 /dev/null,使得构建日志更加简洁,只显示关键信息。
  • cd $(KERNEL_SRC_TMP_PATH) :切换到内核源码所在的临时目录 $(KERNEL_SRC_TMP_PATH)
  • test -f $(DEVICE_PATCH_FILE) :检查设备补丁文件 $(DEVICE_PATCH_FILE) 是否存在。如果文件存在,命令返回真(退出码为 0);如果文件不存在,命令返回假(退出码为非 0)。
  • patch -p1 < $(DEVICE_PATCH_FILE) :应用补丁文件 $(DEVICE_PATCH_FILE)-p1 参数表示剥离补丁路径中的一层目录,即假设补丁是相对于内核源码根目录的一级目录创建的。
  • || true :如果前面的命令(即 test -fpatch 的组合)执行失败(返回非 0 退出码),则执行 true 命令,true 命令总是返回真(退出码为 0)。这可以避免构建过程因为补丁文件不存在或应用补丁失败而中断。

在我拿到的这份源码中没有rk3568.patch这个补丁,所以true很重要,表示此特定补丁为可选项

内核编译配置

在58行中可见如下脚本

 $(KERNEL_MAKE) -C $(KERNEL_SRC_TMP_PATH) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(DEFCONFIG_FILE)

经过上下文的分析可将此脚本解释为

make -C /out/kernel/src_tmp/linux-5.10 ARCH=arm64 CC=/prebuilts/clang/ohos/linux-x86_64/llvm/bin/clang CROSS_COMPILE=/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- rk3568_standard_defconfig
  • -C /out/kernel/src_tmp/linux-5.10 :指定了内核源码所在的目录,make 会进入该目录下进行编译操作,而不是在当前目录。

在这里插入图片描述

  • ARCH=arm64 :定义了目标架构为 ARM64,这意味着要编译出适用于 ARM64 架构设备的内核。
  • CC=/prebuilts/clang/ohos/linux-x86_64/llvm/bin/clang :指定了 C 编译器的路径,这里使用的是 Clang 编译器,它位于 /prebuilts/clang/ohos/linux-x86_64/llvm/bin/ 目录下。

在这里插入图片描述

  • CROSS_COMPILE=/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- :指定了交叉编译前缀,用于构建目标架构(ARM64)上的可执行文件。这个前缀指向了交叉编译工具链的目录,aarch64-linux-gnu- 表示该工具链是针对 aarch64 架构的 Linux 系统的。

在这里插入图片描述

  • rk3568_standard_defconfig :指定使用的内核配置文件。这个文件定义了内核的各种配置选项,如要包含的驱动、功能模块等。它会使内核编译过程按照该配置文件中的设置来进行,生成符合特定硬件平台(这里是 rk3568)需求的内核配置。

通过对上文的分析发现没有对kernel进行打补丁,后经搜索发现在device\board\hihope\rk3568\kernel\目录中包含对kernel的操作,如下

#device\board\hihope\rk3568\kernel\build_kernel.sh
patch -p1 < ${KERNEL_PATCH}#KERNEL_PATCH即为/kernel/linux/patches/linux-5.10/rk3568_patch/kernel.patch

此目录也包含厂家对系统其他的特殊处理,整体流程与上文分析的类似,此处不再详细说明。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/83956.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

考研系列—操作系统:冲刺笔记(4-5章)

目录 第四章 文件管理 1.真题总结文件管理方式 (1)目录文件的FCB就是“目录名-目录地址” (2)普通文件的FCB (3)区分索引文件、顺序文件、索引分配 (4)文件的物理结构 ①连续分配方式 ②链接分配 ③索引分配-使用索引表(一个文件对应一张索引表!!!) 计算考点:超级…

配置URDF模型,调整模型中部件的形状/尺寸,以及在ROS2的Rviz2中进行可视化。

配置URDF模型&#xff0c;调整模型中部件的形状/尺寸&#xff0c;以及在ROS2的Rviz2中进行可视化。 提问 在 ROS2 的rviz2 里面&#xff0c;urdf模型哪些部分选择可视化&#xff0c;哪些部分暂时不呈现在界面上&#xff0c;怎么在rviz2中操作&#xff1f; 回答 在 ROS2 的 …

基于SpringBoot+Vue2的租房售房二手房小程序

角色&#xff1a; 管理员、房东、租客/买家 技术&#xff1a; springbootvue2mysqlmybatispagehelper 核心功能&#xff1a; 租房售房小程序是一个专注于房屋租赁和销售的综合性平台&#xff0c;基于SpringBootVue2MySQLMyBatisPageHelper技术栈开发&#xff0c;为用户提供…

掌握子网划分:优化IP分配与管理

子网划分是通过调整子网掩码&#xff0c;将单一IP网络划分为多个逻辑子网的过程&#xff0c;其核心原理是借用主机位作为子网位以优化地址分配和管理。具体方法与原理如下&#xff1a; 一、子网划分基本原理 核心目的&#xff1a; 减少IP浪费&#xff1a;避免大块地址闲置&…

[原创](现代Delphi 12指南):[macOS 64bit App开发]: TTask创建多线程, 更简单, 更快捷.

[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 开发工具: Visual Studio、Delphi、XCode、…

终极数据结构详解:从理论到实践

终极数据结构详解&#xff1a;从理论到实践 我将从 底层原理、时间复杂度、空间优化、实际应用 和 代码实现 五个维度&#xff0c;彻底解析数据结构。内容涵盖&#xff1a; 线性结构&#xff08;数组、链表、栈、队列&#xff09;非线性结构&#xff08;树、图&#xff09;高…

gvim比较两个文件不同并合并差异

使用 gvim 比较两个文件的不同&#xff1a; 方式一&#xff0c;使用 gvim 同时打开两个待比较的文件。 比较通用方式是采用 gvim -d 选项&#xff0c;具体命令&#xff0c;如下&#xff1a; gvim -d <file1> <file2>方式二&#xff0c;先用 gvim 打开一个文件&am…

15个基于场景的 DevOps 面试问题及答案

第一部分:持续集成和部署 (CI/CD) 场景 1:构建中断 “您的 CI 流水线突然出现‘找不到依赖项’的错误。您会如何处理这个问题?” 回答:首先,我会检查是否有新的依赖项被添加到需求文件中,但这些依赖项并未包含在需求文件中。我还会验证构建服务器是否可以访问互联网来下…

Linux随记(十八)

一、k8s的node节点磁盘 /data已使用率超过 85% , 出现disk pressure &#xff0c;驱逐pod现象 evicted &#xff0c; the node had condition:[DiskPressure] #修改/var/lib/kubelet/config.yaml ]# cat /var/lib/kubelet/config.yaml apiVersion: kubelet.config.k8s.io/v1…

利用Python 进行自动化操作: Pyautogui 库

目录 1. 前言 2. 安装 PyAutoGUI 3. 常见函数介绍 3.1 鼠标操作 3.2 键盘操作 3.3 截图与图像识别 4. 简单案例 5. 总结 1. 前言 我们常常需要与各种软件和系统交互&#xff0c;而人工操作往往耗时且容易出错。这时&#xff0c;PyAutoGUI 就可以帮我们解放双手&#…

如何在Windows本机安装Python并确保与Python.NET兼容

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

oracle数据恢复—oracle数据库执行truncate命令后的怎么恢复数据?

oracle数据库误执行truncate命令导致数据丢失是一种常见情况。通常情况下&#xff0c;oracle数据库误操作删除数据只需要通过备份恢复数据即可。也会碰到一些特殊情况&#xff0c;例如数据库备份无法使用或者还原报错等。下面和大家分享一例oracle数据库误执行truncate命令导致…

计算机二级Python考试的核心知识点总结

以下是计算机二级Python考试的核心知识点总结&#xff0c;结合高频考点和易错点分类整理&#xff1a; 1. **数据类型与运算** ▷ 不可变类型&#xff1a;int, float, str, tuple&#xff08;重点区分list与tuple&#xff09; ▷ 运算符优先级&#xff1a;** > * /…

Vue 组件库发布实战(含 TypeScript 支持)

整理不易&#xff0c;如果本文对你有帮助&#xff0c;欢迎点个【赞 &#x1f44d;】【收藏 ⭐】【关注 &#x1f9e1;】 &#x1f4e6;Vue 组件库发布实战&#xff08;含 TypeScript 支持&#xff09; 在上一篇中我们完成了一个基础 Vue 3 组件的 npm 发布流程。本文将升级内容…

新版双紫擒龙、紫紫红黄、动能二号源码指标源码公式讲解

双紫擒龙量化指标公式源码&#xff0c;双紫擒龙紫紫红黄2025升级版的量化指标龙头模型............ 实战举例&#xff0c;量化擒龙------副图源码&#xff0c;如下&#xff1a; DIF:EMA(CLOSE,12)-EMA(CLOSE,26); DEA:EMA(DIF,9); ABC2:REF(CLOSE,1); ABC3:IF((CLOSE-ABC2…

c++中锁类型对比与实战

C++中的锁类型对比与实战:std::lock_guard、std::unique_lock、std::shared_lock 在多线程编程中,合理地使用锁是保证数据一致性和线程安全的关键。C++标准库提供了多种锁类型,每种都有其适用场景和性能特性。本文将深入分析 std::lock_guard、std::unique_lock、std::shar…

iview Switch Tabs TabPane 使用提示Maximum call stack size exceeded堆栈溢出

在vue项目中使用iview 框架部分组件时&#xff0c;直接引入使用报Maximum call stack size exceeded image.png 堆栈溢出 解决方案 更换组件名称就可以了 image.png 或 image.png 就可以了 猜测是因为和vue自己提供的组件名称一致了&#xff0c;重名问题导致的&#xff0c;具体…

初识结构体,整型提升及操作符的属性

目录 一、结构体成员访问操作符1.1 结构体二、操作符的属性&#xff1a;优先级、结合性2.1 优先级2.2 结合性C 运算符优先级 三、表达式求值3.1 整型提升3.2 算数转化 总结 一、结构体成员访问操作符 1.1 结构体 C语言已经提供了内置类型&#xff0c;如&#xff1a;char,shor…

JVM-内存结构

&#x1f9e9; 一、JVM内存五大核心结构详解 &#x1f4cc; 1. 程序计数器&#xff08;Program Counter Register&#xff09; 特性说明作用记录当前线程执行的字节码行号指示器&#xff08;分支/循环/异常处理的核心&#xff09;线程私有✅ 每个线程独立存储指令位置异常❌ …

从 Revit 到 3DTiles:GISBox RVT 切片器如何让建筑图元在 Web 端展示

在GIS&#xff08;地理信息系统&#xff09;行业蓬勃发展的当下&#xff0c;数据处理与展示的效率和精准度成为关键。GISBox作为一款功能强大的一站式三维GIS数据编辑、转换、发布平台&#xff0c;凭借其独特的“RVT切片器”功能&#xff0c;在RVT图元处理方面也有着不俗的表现…