积分300 / 贡献0

提问5答案被采纳4文章45

[经验分享] 如何优雅的了解OpenHarmony-v4.1-Release的init启动流程 原创

润开鸿_闻飞 显示全部楼层 发表于 2024-5-22 17:49:39

itopen组织 1、提供OpenHarmony优雅实用的小工具 2、手把手适配riscv + qemu + linux的三方库移植 3、未来计划riscv + qemu + ohos的三方库移植 + 小程序开发 4、一切拥抱开源,拥抱国产化

一、启动概述

在产品代码成功编译通过后,开始进行下一步的运行调测阶段,而运行调测第一步便需要了解系统的启动过程。对于OpenHarmony来说,系统启动流程如下:

---> uboot启动
    ---> uboot启动内核
        ---> 内核挂载根文件系统(此时为ramdisk文件系统)
            ---> 运行ramdisk中的第一个程序
                ---> 根据fstab中内容挂载文件系统
                    ---> 切换root路径为/usr
                        ---> 第一个程序为init则进行系统初始化
                        ---> 第一个程序为init_early则通过execv启动init

关于uboot启动到内核挂载根文件系统部分属于Linux内容,这里不做介绍,以下我们开始来介绍从ramdisk启动的第一个程序,我们以init_early模式为例开启我们新的篇章

二、ramdisk文件系统介绍

2.1 什么是ramdisk文件系统

ramdisk是一种将内存中的的一块区域作为物理磁盘来使用的一种技术,也可以说,ramdisk是在一块内存区 域中创建的块设备,用于存放文件系统。对于用户来说,可以把ramdisk与通常的硬盘分区同等对待来使用。ramdisk不适合作为长期保存文件的介质,掉电后ramdisk的内容会消失。

2.2 ramdisk文件系统和ramdisk.img有什么关系

在Linux中,根文件系统是需要挂载到实际的物理磁盘中的,而ramdisk.img便是ramdisk文件系统挂载的磁盘,即ramdisk.img是ramdisk文件系统的打包镜像。 可以对比rootfs,我们通过busybox制作出来的是rootfs文件系统,但是实际启动使用的时候我们时我们需要将rootfs文件系统打包制作成rootfs.ext4一样。

三、init_early程序介绍

3.1 init_early程序注意事项

init_early程序作为第一个启动的程序,由于当前挂载的文件系统为ramdisk文件系统,该系统的目的仅仅是为了拉起OpenHarmony真正的文件系统,可以说仅仅是为了init_early程序的运行,因此内部的库很少,仅有以下内容,所以init_early程序仅可以依赖以下这些库

wen_fei@rh-Z790-UD:~/OpenHarmony/dayu800-v4.1-release/out/dayu800/packages/phone/ramdisk/lib64
$ tree
.
├── chipset-pub-sdk
│   ├── libpcre2.z.so
│   ├── libsec_shared.z.so
│   └── libselinux.z.so
├── libclang_rt.asan.so
├── libc++.so
├── libc.so
├── libinit_module_engine.so -> libinit_stub_empty.so
├── libinit_stub_empty.so
├── libload_policy.z.so
└── platformsdk
    └── librestorecon.z.so

3.2 为什么要有init_early程序

作为第一个基于ramdisk文件系统启动的程序,能够依赖的库有限,因此能实现的功能相对也不能复杂,通过使用init_early拉起init进程可以在尽可能减小ramdisk.img大小的同时很好的让init程序开发更加丰富的内容。 其次如果init程序加载有问题也可以通过init_early程序先启动到shell,然后在shell中运行init进行调测。 以上内容均为个人猜想。

3.3 init_early代码路径

该部分代码的编译参考:base/startup/init/services/init/standard/BUILD.gn 其main函数位于:base/startup/init/services/init/standard/main_early.c

3.4 init_early代码介绍

从其main_early.c代码中可以看出init_early主要完成以下几个功能

  • 忽略终端信号,将SIGPIPE交给系统处理

  • 使能InitLog的INIT_INFO级别(非核心)

  • 初始化EarlyLog(非核心)

  • 创建常用的文件和设备节点

  • 执行钩子函数,一般钩子链表是通过attribute((constructor))构造的函数添加的

  • 确实是否为升级模式

  • 根据ramdisk镜像中的fstab文件挂载镜像

  • 启动第二阶段init

    • 关闭stdio(此时便不能通过printf打印log)
    • 切换root路径为/usr(system文件系统)
    • 让init程序代码当前的init_early程序进行

注意这里是程序不是进程,因为init_early在ramdisk中是软链接为init,因此进程对应的是init,而不是init_early

四、init启动介绍

4.1 init运行前准备工作

由于init_early的铺垫,此时init启动的实际文件系统已经不在ramdisk文件系统中了,而是位于system文件系统中。因此链接库的路径指定是通过etc/ld-musl-namespace-riscv64.ini该文件中设置的路径按照顺序链接的,所以首先必须确定system镜像中是否有该文件。 在init程序中有很多函数通过MODULE_CONSTRUCTOR将其添加到了Hook链表中,在init实际运行的时候会调用HOOK的执行接口,将所有的预处理函数调用执行。

4.2 init启动失败调测

如果init_early加载init程序运行直接失败,我们可以在init_early最后添加如下代码后让串口进入shell,然后在shell中直接运行init跟踪定位

execv("/bin/sh", NULL);

4.3 init启动的流程

这部分就通过init的main函数进行阅读理解了,注意HOOK链表项都是通过MODULE_CONSTRUCTOR接口在main函数执行前添加的,详细请了解gcc的 __attribute__((constructor))属性 init的main函数位于:base/startup/init/services/init/main.c

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

精彩评论2

conceptcon

沙发 发表于 2024-8-2 17:01:18
请教一下,我从RK官方下载的uboot,无法启动OpenHarmnoy5.0beta。但是可以启动OpenHarmnoy4.0。出错log提示,/bin/init文件不存在,帮忙看看。谢谢。

润开鸿_闻飞

发表于 2024-8-5 23:14  IP属地: 江苏省扬州市

回复 conceptcon: 你用的是OpenHarmony的原生代码还是你有修改?

【1 条回复】

Copyright   ©2023  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部