OpenHarmony-1.启动流程

  • OpenHarmony启动流程

1.kernel的启动

流程图如下所示:
在这里插入图片描述  OpenHarmony(简称OH)的标准系统的底层系统是linux,所以调用如下代码:

linux-5.10/init/main.c:
noinline void __ref rest_init(void)
{
	struct task_struct *tsk;
	int pid;

	rcu_scheduler_starting();
	/*
	 * We need to spawn init first so that it obtains pid 1, however
	 * the init task will end up wanting to create kthreads, which, if
	 * we schedule it before we create kthreadd, will OOPS.
	 */
	pid = kernel_thread(kernel_init, NULL, CLONE_FS);
	...
}
static int __ref kernel_init(void *unused)
{
    ...
	if (!try_to_run_init_process("/sbin/init") ||
	    !try_to_run_init_process("/etc/init") ||
	    !try_to_run_init_process("/bin/init") ||
	    !try_to_run_init_process("/bin/sh"))
		return 0;

	panic("No working init found.  Try passing init= option to kernel. "
	      "See Linux Documentation/admin-guide/init.rst for guidance.");
}

  由于OH标准系统是基于kernel内核开发的,所以启动init进程,那么OH的init进程的入口为/base/startup/init/services/init/main.c中。

2.init 进程模块架构

在这里插入图片描述

  • 基础环境初始化:init 进程挂载 tmpfs 和 procfs,创建基本的 dev 设备节点,提供一个基本的根文件系统。

    • tmpfs:这是一个内存上的文件系统,用于存储临时数据,比如在启动期间创建的目录、缓存等。它不会持久化到磁盘,当系统重启时会自动清除。
    • procfs:这个文件系统提供内核运行时信息的接口,如进程列表、系统配置、硬件状态等。init进程通常会挂载procfs,以便在启动早期获取和管理这些信息。
  • 从/proc/cmdline中读取fstab分区表。

  • 热插拔事件监听:init 进程启动 ueventd 来监控内核中的设备热插拔事件,为新插入的 block 设备分区(如 system和 vendor 分区)创建相应的 dev 设备节点。当设备被插入或移除时,内核会通过 uevent(用户空间事件)机制发送消息给 ueventd。ueventd作为系统服务的一部分,负责监听这些netlink事件,并根据接收到的事件类型动态管理相应的设备节点。

  在OH中BUILD.gn用于编译构建模块的。

 base/startup/init/services/init/standard/BUILD.gn:
 15 init_common_sources = [
 16   "../init_capability.c",
 17   "../init_common_cmds.c",
 18   "../init_common_service.c",
 19   "../init_config.c",
 20   "../init_group_manager.c",
 21   "../init_service_file.c",
 22   "../init_service_manager.c",
 23   "../init_service_socket.c",
 24   "../main.c",
 25 ]

 33 ohos_executable("init") {
 34   sources = [
 35     "../adapter/init_adapter.c",
 36     "../standard/device.c",
 37     "../standard/fd_holder_service.c",
 38     "../standard/init.c",
 39     "../standard/init_cmdexecutor.c",
 40     "../standard/init_cmds.c",
 41     "../standard/init_control_fd_service.c",
 42     "../standard/init_jobs.c",
 43     "../standard/init_mount.c",
 44     "../standard/init_reboot.c",
 45     "../standard/init_service.c",
 46     "../standard/init_signal_handler.c",
 47     "../standard/switch_root.c",
 48   ]
 49
 50   modulemgr_sources = [
 51     "//base/startup/init/interfaces/innerkits/hookmgr/hookmgr.c",
 52     "//base/startup/init/interfaces/innerkits/modulemgr/modulemgr.c",
 53   ]
 54   sources += modulemgr_sources

  从BUILD.gn看到OH标准系统的init进程的入口就是init_common_sources的main.c。

base/startup/init/services/init/main.c:
#include <signal.h>
#include "init.h"
#include "init_log.h"

static const pid_t INIT_PROCESS_PID = 1;

int main(int argc, char * const argv[])
{
    int isSecondStage = 0;
    (void)signal(SIGPIPE, SIG_IGN);
    // Number of command line parameters is 2
    //从kernel启动的init进程并未携带任何参数,这里是init的第一阶段
    if (argc == 2 && (strcmp(argv[1], "--second-stage") == 0)) {
        isSecondStage = 1;
    }
    if (getpid() != INIT_PROCESS_PID) {
        INIT_LOGE("Process id error %d!", getpid());
        return 0;
    }
    EnableInitLog(INIT_INFO);
    //第一次这里走的是SystemPrepare
    if (isSecondStage == 0) {
        SystemPrepare();
    } else {
        LogInit();
    }
    SystemInit();
    //启动rcs进程
    SystemExecuteRcs();
    SystemConfig();
    SystemRun();
    return 0;
}

  这里将init进程的代码分成了通用的和特有的两部分,共同的代码均在 /base/startup/init/services/init/文件夹下,其中有lite/和standard/分别用来构建小型系统和标准系统的init进程。这里主要分析标准进程的启动流程。

2.1.SystemPrepare

  由于从kernel进程启动的init进程并未传递任何参数,所以会先执行SystemPrepare:

base/startup/init/services/init/standard/init.c:
225 void SystemPrepare(void)
226 {
227     MountBasicFs();     //挂载一些基本目录并创建一些设备节点
228     CreateDeviceNode();
229     LogInit();
230     // Make sure init log always output to /dev/kmsg.
231     EnableDevKmsg();
232     INIT_LOGI("Start init first stage.");
233     HookMgrExecute(GetBootStageHookMgr(), INIT_FIRST_STAGE, NULL, NULL);
234     // Only ohos normal system support
235     // two stages of init.
236     // If we are in updater mode, only one stage of init.
237     if (InUpdaterMode() == 0) {  //检查是否处于升级模式,如果没有处于升级模式,就进入init第二阶段
238         StartInitSecondStage();
239     }
240 }
  • SystemPrepare主要工作:
    挂载一些基本目录,比如/dev,/mnt,/storage,/dev/pts,/proc,/sys,/sys/fs/selinux,接着创建一些设备节点比如/dev/null,/dev/random,/dev/urandom 等,检查系统是否处于升级模式,如果不处于升级模式就启动init的第二阶段。

2.2.StartInitSecondStage

base/startup/init/services/init/standard/init.c
static void StartInitSecondStage(void)
{
    int requiredNum = 0;
    //从/proc/cmdline中读取fstab分区表
    Fstab *fstab = LoadRequiredFstab();
    char **devices = (fstab != NULL) ? GetRequiredDevices(*fstab, &requiredNum) : NULL;
    if (devices != NULL && requiredNum > 0) {
        //启动Ueventd进程
        int ret = StartUeventd(devices, requiredNum);
        if (ret == 0) {
            //挂载分区
            ret = MountRequriedPartitions(fstab);
        }
        FreeStringVector(devices, requiredNum);
        devices = NULL;
        ReleaseFstab(fstab);
        fstab = NULL;
        if (ret < 0) {
            // If mount required partitions failure.
            // There is no necessary to continue.
            // Just abort
            INIT_LOGE("Mount required partitions failed; please check fstab file");
            // Execute sh for debugging
#ifndef STARTUP_INIT_TEST
            execv("/bin/sh", NULL);
            abort();
#endif
        }
    }

    if (fstab != NULL) {
        ReleaseFstab(fstab);
        fstab = NULL;
    }
    // It will panic if close stdio before execv("/bin/sh", NULL)
    CloseStdio();
    //启动init进程的第二阶段
    INIT_LOGI("Start init second stage.");
    SwitchRoot("/usr");
    // Execute init second stage
    char * const args[] = {
        "/bin/init",
        "--second-stage",
        NULL,
    };
    //启动init进程并传递参数--second-stage 
    if (execv("/bin/init", args) != 0) {
        INIT_LOGE("Failed to exec \"/bin/init\", err = %d", errno);
        exit(-1);
    }
}
  • StartInitSecondStage函数主要就是读取分区表并挂载同时启动Ueventd进程接着再次调用init并传递–second-stage参数。这里的执行execv函数将不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程ID等一些表面上的信息仍保持原样。只有调用失败了,它们才会返回一个-1,从原程序的调用点接着往下执行。所以接下来的都是init第二阶段的执行过程。再次启动init进程后,当然还是走到了/base/startup/init/services/init/main.c不过不同的是由于携带了–second-stage参数,所以会走到LogInit。接着串行执行SystemInit, SystemExecuteRcs,SystemConfig和SystemRun。

startup/init/services/etc/init.cfg

refer to

  • https://huaweicloud.csdn.net/64df3b15dc60580edc7735f4.html

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HTB:Precious[WriteUP]

目录 连接至HTB服务器并启动靶机 使用nmap对靶机TCP端口进行开放扫描 使用curl访问靶机80端口 使用ffuf爆破一下子域 使用浏览器访问该域名 使用curl访问该域名响应头 使用exiftool工具查看该pdf信息 横向移动 USER_FLAG&#xff1a;adf5793a876a190f0c08b3b6247cec32…

jsmind 思维导图 + monaco-editor + vue3 + ts

Index.vue: <template><div class"m-jsmind-wrap"><div class"m-jsmind-header"><el-button type"primary" click"() > handleReset()">重置</el-button><el-button type"primary" cl…

在arm64架构下, Ubuntu 18.04.5 LTS 用命令安装和卸载qt4、qt5

问题&#xff1a;需要在 arm64下安装Qt&#xff0c;QT源码编译失败以后&#xff0c;选择在线安装&#xff01; 最后安装的版本是Qt5.9.5 和QtCreator 4.5.2 。 一、ubuntu安装qt4的命令(亲测有效)&#xff1a; sudo add-apt-repository ppa:rock-core/qt4 sudo apt updat…

AIGC学习笔记(5)——AI大模型开发工程师

文章目录 AI大模型开发工程师004 垂直领域的智能在线搜索平台1 智能在线搜索平台需求分析大模型不够“聪明”增强大模型的方式需求分析2 智能在线搜索平台方案设计方案设计技术选型大模型版本GLM-4大模型注册使用Google Cloud平台注册创建可编程的搜索引擎3 智能在线搜索平台代…

【React】状态管理之Redux

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 状态管理之Redux引言1. Redux 的核心概念1.1 单一数据源&#xff08;Single Sou…

Unity类银河战士恶魔城学习总结(P124 CharacterStats UI玩家的UI)

【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili 教程源地址&#xff1a;https://www.udemy.com/course/2d-rpg-alexdev/ 本章节实现了玩家属性栏&#xff0c;仓库&#xff0c;物品栏UI的制作 UI_StatSlot.cs 这个脚本是用来在Unity的UI上显示玩家属性&#xf…

蓝桥杯每日真题 - 第7天

题目&#xff1a;&#xff08;爬山&#xff09; 题目描述&#xff08;X届 C&C B组X题&#xff09; 解题思路&#xff1a; 前缀和构造&#xff1a;为了高效地计算子数组的和&#xff0c;我们可以先构造前缀和数组 a&#xff0c;其中 a[i] 表示从第 1 个元素到第 i 个元素的…

Llama旋转位置编码代码实现及详解

旋转位置编码RoPE 在旋转位置编码与Transformer和BERT之间的区别中介绍了旋转位置编码&#xff08;RoPE&#xff09;的特点和优势&#xff0c;这种输入长度动态可变的优势使得在Llama编码时&#xff0c;不需要掩码将多余的嵌入掩住。为了详细了解RoPE是如何实现的&#xff0c;…

WebSocket和HTTP协议的性能比较与选择

WebSocket和HTTP协议的性能比较与选择 引言&#xff1a; 在web应用开发中&#xff0c;无论是实时聊天应用、多人在线游戏还是实时数据传输&#xff0c;网络连接的稳定性和传输效率都是关键要素之一。目前&#xff0c;WebSocket和HTTP是两种常用的网络传输协议&#xff0c;它们…

WebRTC项目一对一视频

开发步骤 1.客户端显示界面 2.打开摄像头并显示到页面 3.websocket连接 4.join、new-peer、resp-join信令实现 5.leave、peer-leave信令实现 6.offer、answer、candidate信令实现 7.综合调试和完善 1.客户端显示界面 步骤&#xff1a;创建html页面 主要是input、button、vide…

GIS基础知识:WKT格式、WKB格式

什么是WKT格式&#xff1f; WKT&#xff08;Well-Known Text&#xff09;是一种用于描述地理空间几何对象的文本格式。 这种格式是由Open Geospatial Consortium&#xff08;OGC&#xff09;定义并维护的一种开放标准&#xff0c;主要用于在不同的GIS系统和数据库之间交换空间…

力扣(LeetCode)611. 有效三角形的个数(Java)

White graces&#xff1a;个人主页 &#x1f649;专栏推荐:Java入门知识&#x1f649; &#x1f439;今日诗词:雾失楼台&#xff0c;月迷津渡&#x1f439; ⛳️点赞 ☀️收藏⭐️关注&#x1f4ac;卑微小博主&#x1f64f; ⛳️点赞 ☀️收藏⭐️关注&#x1f4ac;卑微小博主…

Mac Nginx 前端打包部署

安装homebrew /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 安装Nginx brew install nginx nginx相关命令 nginx启动命令&#xff1a;nginx nginx -s reload #重新加载配置 nginx -s reopen #重启 nginx -s stop #…

利用VMware workstation pro 17安装 Centos7虚拟机以及修改网卡名称

通过百度网盘分享的文件&#xff1a;安装虚拟机必备软件 链接&#xff1a;https://pan.baidu.com/s/1rbYhDh8x1hTzlSNihm49EA?pwdomxy 提取码&#xff1a;omxy 123网盘 https://www.123865.com/s/eXPrVv-UsKch 提取码:eNcy 先自行安装好VMware workstation pro 17 设置虚拟机…

《实时流计算系统设计与实现》-Part 2-笔记

做不到实时 做不到实时的原因 实时计算很难。通过增量计算的方式来间接获得问题的&#xff08;伪&#xff09;实时结果&#xff0c;即使这些结果带有迟滞性和近似性&#xff0c;但只要能够带来尽可能最新的信息&#xff0c;那也是有价值的。 原因可分成3个方面&#xff1a; …

《C陷阱与缺陷》

文章目录 1、【词法陷阱】1.1 符号与组成符号间的关系1.1 与 1.3 y x/*p 与 y x/(*p)&#xff0c;a-1 与 a - 1 与 a -1, 老版本编译器的处理是不同的&#xff0c;严格的ANSI C则会报错1.4 十进制的 076&#xff0c;会被处理为八进制&#xff0c;ANSI C禁止这种用法&#x…

初阶C++之C++入门基础

大家好&#xff01;欢迎来到C篇学习&#xff0c;这篇文章的内容不会很难&#xff0c;为c的引入&#xff0c;c的重点内容将在第二篇的文章中讲解&#xff0c;届时难度会陡然上升&#xff0c;请做好准备&#xff01; 我们先看网络上的一个梗&#xff1a;21天内⾃学精通C 好了&am…

Maven 构建项目

Maven 是一个项目管理和构建工具&#xff0c;主要用于 Java 项目。它简化了项目的构建、依赖管理、报告生成、发布等一系列工作。 构建自动化&#xff1a;Maven 提供了一套标准化的构建生命周期&#xff0c;包括编译、测试、打包、部署等步骤&#xff0c;通过简单的命令就可以执…

Android中桌面小部件的开发流程及常见问题和解决方案

在Android中&#xff0c;桌面小部件&#xff08;App Widget&#xff09;是应用程序可以在主屏幕或其他地方显示的一个可视化组件&#xff0c;提供简化信息和交互功能。Android桌面小部件的framework为开发者提供了接口&#xff0c;使得可以创建和更新小部件的内容。以下是Andro…

opencv(c++)----图像的读取以及显示

opencv(c)----图像的读取以及显示 imread: 作用&#xff1a;读取图像文件并将其加载到 Mat 对象中。参数&#xff1a; 第一个参数是文件路径&#xff0c;可以是相对路径或绝对路径。第二个参数是读取标志&#xff0c;比如 IMREAD_COLOR 表示以彩色模式读取图像。 返回值&#x…