鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙看这篇或许真的够了 | 百篇博客分析HarmonyOS源码 | v50.05

原创
04/23 09:20
阅读数 1.2W

将 HarmonyOS | 鸿蒙 研究到底 < 国内 | 国外 >

在这里插入图片描述

百篇博客系列篇.本篇为:

几点说明

编译鸿蒙

sourecinsight多年的使用习惯,爱不释手并为电脑性能计,所以选择以windows + docker方式编译鸿蒙. kernel_liteos_a_note

本篇记录编译鸿蒙的过程,以备后续不用再去一大堆无效的误导式软文中搜寻芝麻大点有用的信息,那样真挺费时费心力.

编译环境

先安装 Docker Desktop 下载windows版本一直下一步.

在windows下拉取openharmony-docker官方镜像,Docker方式获取编译环境 强烈推荐这么做.

docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.3

2.36G, 拉取看网速, 大概10分钟后成功了,有了镜像

PS E:\harmony\kernel_liteos_a_note> docker images
REPOSITORY                                                               TAG       IMAGE ID       CREATED       SIZE  
swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker   0.0.3     50d0aa6ea9ba   2 weeks ago   2.36GB

vscode对docker的管理插件非常的强大,管理镜像和容器的工作就交给它了.

启动docker,创建好容器,本文的选择是这样的,当然大家可以灵活处理,命名. 本文使用E:\harmony\code-1.0 E:\harmony\docker,这两个文件夹一定要先创建好.
kernel_liteos_a_note

容器创建成功后可以在 vscode 右键容器inspect查看到绑定的目录.

"HostConfig": {
    "Binds": [
        "E:\\harmony\\code-1.0:/home/harmony",
        "E:\\harmony\\docker:/home/docker"
    ],

本文这样做的目的为了在windows上能方便的查看文件.harmony目录用于下载编译源码目录,另外一个docker放其他无关文件 repo方式下载源码 进入容器,vscode右键容器 Attach shell,再进入/home/harmony目录

root@5e3abe332c5a:/home/harmony#repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify
....
root@5e3abe332c5a:/home/harmony#repo sync -c

这个过程也是比网速.慢慢等吧. 下载完成之后的样子

Updating files: 100% (7561/7561), done.ird_party_harfbuzzUpdating files:   2% (222/7561)
Updating files: 100% (2983/2983), done.ird_party_iniparserUpdating files:   8% (243/2983)
Updating files: 100% (500/500), done.third_party_libjpegUpdating files:  61% (309/500)
Updating files: 100% (8556/8556), done.ird_party_libuuidUpdating files:   4% (370/8556)
Updating files: 100% (379/379), done.third_party_ltpUpdating files:  64% (243/379)
Updating files: 100% (1015/1015), done.ird_party_lwipUpdating files:  34% (348/1015)
Updating files: 100% (3118/3118), done.hird_party_mtd_utilsUpdating files:   9% (297/3118)
Updating files: 100% (3098/3098), done.hird_party_muslUpdating files:  10% (331/3098)
Updating files: 100% (525/525), done. third_party_rt_threadUpdating files:  66% (348/525)
Updating files: 100% (904/904), done. third_party_unityUpdating files:  29% (266/904)
Checking out projects: 100% (113/113), done.
repo sync has finished successfully.
root@5e3abe332c5a:/home/harmony# ls
applications  base  build  build.py  developtools  device  docs  domains  drivers  foundation  kernel  prebuilts  test  third_party  utils  vendor
root@5e3abe332c5a:/home/harmony#

编译前提

  • Linux服务器,Ubuntu16.04及以上64位系统版本。
  • Python 3.7.4及以上。
  • OpenHarmony源码build_lite仓下载成功。

按照上面的方法,能到这里说明这三个条件都已经满足了.下面安装编译工具

编译过程 | 安装 hb

hb全称应该是harmonyos build(猜的哈) 在源码的根目录执行:

root@5e3abe332c5a:/home/harmony#python3 -m pip install --user build/lite

执行hb -h有相关帮助信息,有打印信息即表示安装成功:

root@5e3abe332c5a:/home/harmony/# hb -v
[OHOS INFO] hb version 0.3.8
root@5e3abe332c5a:/home/harmony/# hb -h
usage: hb

OHOS build system

positional arguments:
  {build,set,env,clean,deps}
    build               Build source code
    set                 OHOS build settings
    env                 Show OHOS build env
    clean               Clean output
    deps                OHOS components deps

optional arguments:
  -h, --help            show this help message and exit
  -v, --version         show program's version number and exit

另外hb的卸载方法如下:

python3 -m pip uninstall ohos-build

安装编译工具hb成功后,开始下一步设置编译路径.

编译命令 | hb set

先看看它的帮助信息

root@5e3abe332c5a:/home/harmony#hb set -h
usage: hb set [-h] [-root [ROOT_PATH]] [-p]

optional arguments:
  -h, --help            Show this help message and exit.
  -root [ROOT_PATH], --root_path [ROOT_PATH]
                        Set OHOS root path.
  -p, --product         Set OHOS board and kernel.
  • hb set 后无参数,进入默认设置流程
  • hb set -root [ROOT_PATH] 直接设置代码根目录
  • hb set -p --product 设置要编译的产品

本篇选择当前路径 .

root@5e3abe332c5a:/home/harmony#hb set
[OHOS INFO] Input code path: .
OHOS Which product do you need?  (Use arrow keys)

hisilicon
❯ ipcamera_hispark_aries
wifiiot_hispark_pegasus
ipcamera_hispark_taurus

直接回车,本篇选择了ipcamera_hispark_aries,这三个对应平台的关系如下

Hi3518:ipcamera_hispark_aries@hisilicon
Hi3861:wifiiot_hispark_pegasus@hisilicon
Hi3516:ipcamera_hispark_taurus@hisilicon

编译命令 | hb env

设置路径成功后,可查看下当前设置信息

root@5e3abe332c5a:/home/harmony# hb env
[OHOS INFO] root path: /home/harmony
[OHOS INFO] board: hispark_aries
[OHOS INFO] kernel: liteos_a
[OHOS INFO] product: ipcamera_hispark_aries
[OHOS INFO] product path: /home/harmony/vendor/hisilicon/hispark_aries
[OHOS INFO] device path: /home/harmony/device/hisilicon/hispark_aries/sdk_liteos

编译命令 | hb build

同样看下它的帮助信息,可以选择全编,编单个模块,只编译ndk,看具体的开发场景.

root@5e3abe332c5a:/home/harmony# hb build -h
usage: hb build [-h] [-b BUILD_TYPE] [-c COMPILER] [-t [TEST [TEST ...]]] [--dmverity] [--tee] [-p PRODUCT]
                [-f] [-n] [-T [TARGET [TARGET ...]]] [-v] [-shs]
                [component [component ...]]

positional arguments:
  component             name of the component

optional arguments:
  -h, --help            show this help message and exit
  -b BUILD_TYPE, --build_type BUILD_TYPE
                        release or debug version
  -c COMPILER, --compiler COMPILER
                        specify compiler
  -t [TEST [TEST ...]], --test [TEST [TEST ...]]
                        compile test suit
  --dmverity            Enable dmverity
  --tee                 Enable tee
  -p PRODUCT, --product PRODUCT
                        build a specified product with {product_name}@{company}, eg: camera@huawei
  -f, --full            full code compilation
  -n, --ndk             compile ndk
  -T [TARGET [TARGET ...]], --target [TARGET [TARGET ...]]
                        Compile single target
  -v, --verbose         show all command lines while building
  -shs, --sign_haps_by_server
                        sign haps by server

解读

  • hb build后无参数,会按照设置好的代码路径、产品进行编译,编译选项使用与之前保持一致。
  • hb build component:基于设置好的产品对应的单板、内核,单独编译组件(e.g.:hb build kv_store)。
  • hb build -p PRODUCT:免set编译产品,该命令可以跳过set步骤,直接编译产品。

本文选择全编 hb build -f,拼电脑性能,搞开发一定要搞台好电脑,时间就是生命,内存最好32G,过程大概10分钟.

root@5e3abe332c5a:/home/harmony#hb build -f
...
[OHOS INFO] [1587/1590] STAMP obj/test/xts/acts/build_lite/acts_generate_module_data.stamp
[OHOS INFO] [1588/1590] ACTION //test/xts/acts/build_lite:acts(//build/lite/toolchain:linux_x86_64_ohos_clang)
[OHOS INFO] [1589/1590] STAMP obj/test/xts/acts/build_lite/acts.stamp
[OHOS INFO] [1590/1590] STAMP obj/build/lite/ohos.stamp
[OHOS INFO] ipcamera_hispark_aries build success
root@5e3abe332c5a:/home/harmony#

会多出一个out目录,每个的目录含义如下

目录名          描述
applications    应用程序样例,包括wifi-iot,camera等
base            基础软件服务子系统集&硬件服务子系统集
build           组件化编译、构建和配置脚本
docs            说明文档
domains         增强软件服务子系统集
drivers         驱动子系统
foundation      系统基础能力子系统集
kernel          内核子系统
prebuilts       编译器及工具链子系统
test            测试子系统
third_party     开源第三方组件
utils           常用的工具集
vendor          厂商提供的软件
build.py        编译脚本文件
out             编译后生成

编译命令 | hb clean

清除out目录对应产品的编译产物,仅剩下args.gn、build.log。清除指定路径可输入路径参数:hb clean xxx/out/xxx,否则将清除hb set的产品对应out路径.此处不要去敲它,它的帮助提示信息如下,

root@5e3abe332c5a:/home/harmony# hb clean -h
usage: hb clean [-h] [out_path]

positional arguments:
  out_path    clean a specified path.

optional arguments:
  -h, --help  show this help message and exit

编译输出 | out 目录

out为编译结果输出目录

输出目录 : out/hispark_aries/ipcamera_hispark_aries
root@5e3abe332c5a:/home/harmony# cd out/hispark_aries/ipcamera_hispark_aries
root@5e3abe332c5a:/home/harmony/out/hispark_aries/ipcamera_hispark_aries#
root@5e3abe332c5a:/home/harmony/out/hispark_aries/ipcamera_hispark_aries# ls
args.gn      build.log      bundle_daemon_tool.map  dev_tools       libs              NOTICE_FILE  OHOS_Image.asm  rootfs            suites     toggleButtonTest.map  userfs            vendor
bin          build.ninja    config                  etc             liteos.bin        obj          OHOS_Image.bin  rootfs_jffs2.img  test       toolchain.ninja       userfs_jffs2.img
bm_tool.map  build.ninja.d  data                    foundation.map  media_server.map  OHOS_Image   OHOS_Image.map  server.map        test_info  unstripped            usr

系列篇会详细讲解启动过程,此处进入bin目录瞅瞅都有些啥好宝贝.

root@5e3abe332c5a:/home/harmony/out/hispark_aries/ipcamera_hispark_aries/bin# ls
ai_server        module_ActsAbilityMgrTest.bin   module_ActsGraphVersionTest.bin  module_ActsJFFS2CapabilityTest.bin  module_ActsNFSTest.bin           module_ActsSurfaceTest.bin         os_dump
apphilogcat      module_ActsBootstrapTest.bin    module_ActsHeapBaseTest.bin      module_ActsJFFS2DACTest.bin         module_ActsParameterTest.bin     module_ActsSysApiTest.bin          query.bin
appspawn         module_ActsBundleMgrTest.bin    module_ActsHilogTest.bin         module_ActsJFFS2Test.bin            module_ActsPMSTest.bin           module_ActsTimeApiTest.bin         shell
bundle_daemon    module_ActsColorTest.bin        module_ActsIoApiTest.bin         module_ActsKvStoreTest.bin          module_ActsProcessApiTest.bin    module_ActsTransformTest.bin       tftp
CalcSubTest.bin  module_ActsDyloadTest.bin       module_ActsIpcMqTest.bin         module_ActsListTest.bin             module_ActsRectTest.bin          module_ActsUiInterfaceTest1.bin    wms_server
foundation       module_ActsFutexApiTest.bin     module_ActsIpcPipeTest.bin       module_ActsLwipTest.bin             module_ActsSamgrTest.bin         module_ActsUtilApiTest.bin
hilogcat         module_ActsGeometyr2dTest.bin   module_ActsIpcSemTest.bin        module_ActsMathApiTest.bin          module_ActsSchedApiTest.bin      module_ActsVFATCapabilityTest.bin
init             module_ActsGraphicMathTest.bin  module_ActsIpcShmTest.bin        module_ActsMemApiTest.bin           module_ActsSecurityDataTest.bin  module_ActsVFATDACTest.bin
media_server     module_ActsGraphMemApiTest.bin  module_ActsIpcSignalTest.bin     module_ActsNetTest.bin              module_ActsSoftBusTest.bin       module_ActsVFATTest.bin

这难道都是ELF格式可执行程序? 用readelf命令试下shell就知道了.果然是shell程序,加载它将创建激动人心的shell进程

root@5e3abe332c5a:/home/harmony/out/hispark_aries/ipcamera_hispark_aries/bin# readelf -h shell
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x1000
  Start of program headers:          52 (bytes into file)
  Start of section headers:          25268 (bytes into file)
  Flags:                             0x5000200, Version5 EABI, soft-float ABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         11
  Size of section headers:           40 (bytes)
  Number of section headers:         27
  Section header string table index: 26

再随便选择一个module_ActsListTest.bin看下,这些是鸿蒙用于测试的代码生成的.也是一个个的独立程序.可以在工程里找到他们的身影list_test.cpp,ActsListTest.json等文件

root@5e3abe332c5a:/home/harmony/out/hispark_aries/ipcamera_hispark_aries/bin# readelf -h module_ActsListTest.bin 
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00        
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)     
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0xb000
  Start of program headers:          52 (bytes into file)
  Start of section headers:          172256 (bytes into file)
  Flags:                             0x5000200, Version5 EABI, soft-float ABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         11
  Size of section headers:           40 (bytes)
  Number of section headers:         27
  Section header string table index: 26

解读

仔细比较下这两个ELF的头文件看哪里不一样

  Entry point address:               0x1000
  Entry point address:               0xb000

这是.text代码段的入口地址,但注意这并不是 main函数的地址,真正的入口地址是_start,由它再调用main. 具体看

有详细说明,readelf的功能很强大,有兴趣的可以玩下这个命令,看看elf里面究竟装的啥.

root@5e3abe332c5a:/home/harmony/out/hispark_aries/ipcamera_hispark_aries/bin# readelf -help
readelf: option requires an argument -- 'p'
Usage: readelf <option(s)> elf-file(s)
 Display information about the contents of ELF format files       
 Options are:
  -a --all               Equivalent to: -h -l -S -s -r -d -V -A -I
  -h --file-header       Display the ELF file header
  -l --program-headers   Display the program headers
     --segments          An alias for --program-headers
  -S --section-headers   Display the sections' header
     --sections          An alias for --section-headers
  -g --section-groups    Display the section groups
  -t --section-details   Display the section details
  -e --headers           Equivalent to: -h -l -S
  -s --syms              Display the symbol table
     --symbols           An alias for --syms
  --dyn-syms             Display the dynamic symbol table
  -n --notes             Display the core notes (if present)      
  -r --relocs            Display the relocations (if present)
  -u --unwind            Display the unwind info (if present)
  -d --dynamic           Display the dynamic section (if present)
  -V --version-info      Display the version sections (if present)
  -A --arch-specific     Display architecture specific information (if any)
  -c --archive-index     Display the symbol/file index in an archive
  -D --use-dynamic       Use the dynamic section info when displaying symbols
  -x --hex-dump=<number|name>
                         Dump the contents of section <number|name> as bytes
  -p --string-dump=<number|name>
                         Dump the contents of section <number|name> as strings
  -R --relocated-dump=<number|name>
                         Dump the contents of section <number|name> as relocated bytes
  -z --decompress        Decompress section before dumping it
  -w[lLiaprmfFsoRtUuTgAckK] or
  --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,
               =frames-interp,=str,=loc,=Ranges,=pubtypes,
               =gdb_index,=trace_info,=trace_abbrev,=trace_aranges,
               =addr,=cu_index,=links,=follow-links]
                         Display the contents of DWARF debug sections
  --dwarf-depth=N        Do not display DIEs at depth N or greater
  --dwarf-start=N        Display DIEs starting with N, at the same depth
                         or deeper
  --ctf=<number|name>    Display CTF info from section <number|name>
  --ctf-parent=<number|name>
                         Use section <number|name> as the CTF parent

  --ctf-symbols=<number|name>
                         Use section <number|name> as the CTF external symtab

  --ctf-strings=<number|name>
                         Use section <number|name> as the CTF external strtab

  -I --histogram         Display histogram of bucket list lengths
  -W --wide              Allow output width to exceed 80 characters
  @<file>                Read options from <file>
  -H --help              Display this information
  -v --version           Display the version number of readelf

参数中文说明

    -a  --all 显示全部信息,等价于 -h -l -S-s -r -d -V -A -I.
    -h  --file-header 显示elf文件开始的文件头信息.
    -l  --program-headers --segments 显示程序头(段头)信息(如果有的话)。
    -S  --section-headers --sections 显示区头信息(如果有的话)。
    -g  --section-groups 显示区组信息(如果有的话)。
    -t  --section-details 显示区的详细信息(-S 的)。
    -s  --syms --symbols 显示符号表段中的项(如果有的话)。
    -e  --headers 显示全部头信息,等价于: -h -l -S
    -n  --notes 显示note段(内核注释)的信息。
    -r  --relocs 显示可重定位段的信息。
    -u  --unwind 显示unwind段信息。当前只支持 IA64ELF 的 unwind 段信息。
    -d  --dynamic 显示动态段的信息。
    -V  --version-info 显示版本段的信息。
    -A  --arch-specific 显示CPU构架信息。
    -D  --use-dynamic 使用动态段中的符号表显示符号,而不是使用符号段。
    -x  --hex-dump= 以16进制方式显示指定段内内容。number 指定段表中段的索引,或字符串指定文件中的段名。
    -w[liaprmfFsoR] --debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges] 显示调试段中指定的内容。
    -I  --histogram 显示符号的时候,显示 bucketlist 长度的柱状图。
    -v  --version 显示 readelf 的版本信息。
    -H  --help 显示 readelf 所支持的命令行选项。
    -W  --wide 宽行输出。
    @file   可以将选项集中到一个文件中,然后使用这个 @file 选项载入。

具体的加载过程和elf格式后续有专门的篇幅详细介绍,此处不做说明.

用户进程

grep过滤下干扰的*.bin,剩下的就是平台(Hi3518)需要内核创建的用户态进程.

root@5e3abe332c5a:/home/harmony/out/hispark_aries/ipcamera_hispark_aries/bin# ls | grep -v .bin
ai_server
apphilogcat
appspawn
bundle_daemon
foundation
hilogcat
init
media_server
os_dump
shell
tftp
wms_server

这些服务含义和仓库如下.

ai_server       AI业务子系统            https://gitee.com/openharmony/ai_engine
apphilogcat     小型系统的流水日志功能   https://gitee.com/openharmony/hiviewdfx_hilog_lite
                                       base\hiviewdfx\hilog_lite\services\apphilogcat\hiview_applogcat.c
appspawn        应用孵化模块进程        https://gitee.com/openharmony/startup_appspawn_lite
bundle_daemon   用户程序框架内部工具接口 https://gitee.com/openharmony/appexecfwk_appexecfwk_lite
foundation      foundation系统进程      https://gitee.com/openharmony/distributedschedule_safwk_lite
hilogcat        管理日志打印            https://gitee.com/openharmony/hiviewdfx_hilog_lite
                                       base\hiviewdfx\hilog_lite\services\hilogcat\hiview_logcat.c
init            用户态祖宗进程          1号进程, -> 鸿蒙内核源码分析(特殊进程篇)
media_server    播放模块框架实现        https://gitee.com/openharmony/multimedia_media_lite
os_dump         备份文件系统            utils\native\lite\os_dump\os_dump.c
shell           窥视内核的窗口          3号进程, -> 鸿蒙内核源码分析(shell篇)
tftp            传输文件                third_party\curl\lib\tftp.c
wms_server      窗口管理服务            https://gitee.com/openharmony/graphic_wms

在整个项目工程中能轻易找到他们的入口函数.比如appspawn的启动过程

//base\startup\appspawn_lite\services\src\main.c
int main(int argc, char const argv[])
{
    sleep(1);
    HILOG_INFO(HILOG_MODULE_HIVIEW, "[appspawn] main, enter.");

    // 1. ipc module init
    HOS_SystemInit();

    // 2. register signal for SIGCHLD
    SignalRegist();

    // 3. keep process alive
    HILOG_INFO(HILOG_MODULE_HIVIEW, "[appspawn] main, entering wait.");
    while (1) {
        // pause only returns when a signal was caught and the signal-catching function returned.
        // pause only returns -1, no need to process the return value.
        (void)pause();
    }
}

鸿蒙将服务做成了组件,为最上层的应用程度提供管理/工具类的服务.但这些都是framework层的工作,超出了内核源码分析的范畴.希望后续有机会能去剖析它们.

百篇博客.往期回顾

在加注过程中,整理出以下文章.内容立足源码,常以生活场景打比方尽可能多的将内核知识点置入某种场景,具有画面感,容易理解记忆.说别人能听得懂的话很重要! 百篇博客绝不是百度教条式的在说一堆诘屈聱牙的概念,那没什么意思.更希望让内核变得栩栩如生,倍感亲切.确实有难度,自不量力,但已经出发,回头已是不可能的了.:P 与代码有bug需不断debug一样,文章和注解内容会存在不少错漏之处,但会反复修正,持续更新,.xx代表修改的次数,精雕细琢,言简意赅,力求打造精品内容.

关于 51 .c .h .o

看系列篇文章会常看到 51 .c .h .o,希望这对大家阅读不会造成影响. 分别对应以下四个站点的首个字符,感谢这些站点一直以来对系列篇的支持和推荐,尤其是 oschina gitee ,很喜欢它的界面风格,简洁大方,让人感觉到开源的伟大!

而巧合的是.c .h .o是C语言的头/源/目标文件,这就很有意思了,冥冥之中似有天数,将这四个宝贝以这种方式融合在一起. 51 .c .h .o , 我要CHO ,嗯嗯,hin 顺口 : )

百万汉字注解.百篇博客分析

百万汉字注解 >> 精读鸿蒙源码,中文注解分析, 深挖地基工程,大脑永久记忆,四大码仓每日同步更新< gitee | github | csdn | coding >

百篇博客分析 >> 故事说内核,问答式导读,生活式比喻,表格化说明,图形化展示,主流站点定期更新中< 51cto | csdn | harmony | osc >

关注不迷路.代码即人生

鸿蒙内核源码分析

热爱是所有的理由和答案 - turing

原创不易,欢迎转载,但麻烦请注明出处.

展开阅读全文
打赏
1
2 收藏
分享
加载中
打赏
1 评论
2 收藏
1
分享
返回顶部
顶部