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

 

 

几点说明

  • OpenHarmony全量代码仓库(本仓库) 是开放原子开源基金会 旗下孵化项目 OpenHarmony 的130+个子项目的所有源码.鸿蒙官方是使用repo管理众多git项目,repolinux下很方便,但在windows上使用会有相当的困难,所以将官方所有项目整合成一个.git工程,如此使用git方式便能下载整个鸿蒙系统源码,方便学习使用.本仓库也将每月与官方保持同步.OpenHarmony全量代码仓库(本仓库)已编译通过.

    ....
    [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#
  • kernel_liteos_a_note 是在 开放原子开源基金会 旗下孵化项目 OpenHarmony 的 kernel_liteos_a(鸿蒙内核项目) 基础上给源码加上中文注解的版本.加注版与官方版本保持月月同步.

  •  
  •  

 

编译鸿蒙

sourecinsight多年的使用习惯,爱不释手并为电脑性能计,所以选择以windows + docker方式编译鸿蒙.
[鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙看这篇或许真的够了 | 百篇博客分析HarmonyOS源码 | v50.03_鸿蒙_02]

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

 

编译环境

先安装 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,这两个文件夹一定要先创建好.
[鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙看这篇或许真的够了 | 百篇博客分析HarmonyOS源码 | v50.03_鸿蒙_03]

容器创建成功后可以在 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#

 

编译过程

在源码的根目录执行如下命令安装鸿蒙的编译模块hb

 

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

hb全称应该是harmonyos build system,在鸿蒙内核源码分析(编译过程篇)中有详细介绍.

 

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

设置编译路径,选择当前路径 .

 

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 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

本文选择全编 -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#

每个的目录含义如下

 

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

 

编译输出

out为编译结果输出目录

 

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. 具体看
v51.xx (ELF反汇编篇) | 程序的入口函数并不是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.cint 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层的工作,超出了内核源码分析的范畴.希望后续有机会能去剖析它们.

 

百篇博客.往期回顾

在加注过程中,整理出以下文章.内容立足源码,常以生活场景打比方尽可能多的将内核知识点置入某种场景,具有画面感,容易理解记忆.
说别人能听得懂的话很重要! 百篇博客绝不是百度教条式的在说一堆诘屈聱牙的概念,那没什么意思.更希望让内核变得栩栩如生,倍感亲切.确实有难度,自不量力,但已经出发,回头已是不可能的了.