鸿蒙OS启动流程

启动流程(基于openharmony4.1)

系统上电加载内核后,按照以下流程完成系统各个服务和应用的启动:

  1. 内核加载init进程,一般在bootloader启动内核时通过设置内核的cmdline来指定init的位置。
  2. init进程启动后,会挂载tmpfs,procfs,创建基本的dev设备节点,提供最基本的根文件系统。
  3. init也会启动ueventd监听内核热插拔设备事件,为这些设备创建dev设备节点。包括block设备各个分区设备都是通过此事件创建。
  4. init进程挂载block设备各个分区(system,vendor)后,开始扫描各个系统服务的init启动脚本,并拉起各个SA服务。
  5. samgr是各个SA的服务注册中心,每个SA启动时,都需要向samgr注册,每个SA会分配一个ID,应用可以通过该ID访问SA。
  6. foundation是一个特殊的SA服务进程,提供了用户程序管理框架及基础服务。由该进程负责应用的生命周期管理。
  7. 由于应用都需要加载JS的运行环境,涉及大量准备工作,因此appspawn作为应用的孵化器,在接收到foundation里的应用启动请求时,可以直接孵化出应用进程,减少应用启动时间。

启动子系统内部涉及以下组件:

  • init启动引导组件

    init启动引导组件对应的进程为init进程,是内核完成初始化后启动的第一个用户态进程。init进程启动之后,读取init.cfg配置文件,根据解析结果,执行相应命令(见job解析接口说明)并依次启动各关键系统服务进程,在启动系统服务进程的同时设置其对应权限。

  • ueventd启动引导组件

    ueventd负责监听内核设备驱动插拔的netlink事件,根据事件类型动态管理相应设备的dev节点。

  • appspawn应用孵化组件

    负责接收用户程序框架的命令孵化应用进程,设置新进程的权限,并调用应用程序框架的入口函数。

  • bootstrap服务启动组件

    提供了各服务和功能的启动入口标识。在SAMGR启动时,会调用bootstrap标识的入口函数,并启动系统服务。

图1 启动子系统上下文结构图

在这里插入图片描述

约束与限制

启动恢复子系统源代码目录和适配平台:

表1 启动恢复子系统源代码目录和适配平台

名称适配平台
base/startup/appspawne小型系统设备(参考内存≥1MB)、 标准系统,如Hi3516DV300&nbsp、Hi3518EV300、 RK3568
base/startup/bootstrap_lite轻量系统设备(参考内存≥128KB),如Hi3861V100
base/startup/init小型系统设备(参考内存≥1MB)、标准系统,如Hi3516DV300、Hi3518EV300、RK3568
  • init启动引导组件:

    • 每个系统服务启动时都需要编写各自的启动脚本文件init.cfg,定义各自的服务名、可执行文件路径、权限和其他信息。
    • 每个系统服务各自安装其启动脚本到/system/etc/init目录下,init进程统一扫码执行。
  • 新芯片平台移植时,平台相关的初始化配置需要增加平台相关的初始化配置文件/vendor/etc/init/init.{hardware}.cfg;该文件完成平台相关的初始化设置,如安装ko驱动,设置平台相关的/proc节点信息。

    说明:

    配置文件init.cfg仅支持json格式。

  • bootstrap服务启动组件:需要在链接脚本中配置zInit代码段。
    bootstrap服务启动组件实现了服务的自动初始化,即服务的初始化函数无需显式调用,而是将其使用宏定义的方式申明,就会在系统启动时自动被执行。实现原理是将服务启动的函数通过宏定义的方式申明之后,放在预定义好的zInit代码段中,系统启动的时候调用OHOS_SystemInit接口遍历该代码段并调用其中的函数。因此,需要在链接脚本中添加zInit段,并且在main函数里调用OHOS_SystemInit接口。

    zInit段的添加可参考已有的Hi3861平台的链接脚本,文件路径为vendor/hisi/hi3861/hi3861/build/link/link.ld.S。

    用于实现服务的自动初始化的宏定义接口请参见启动恢复子系统的API接口文档。

    接口说明

    bootstrap服务自动初始化宏如表1所述。

    表1 主要的服务自动初始化宏

    接口名描述
    SYS_SERVICE_INIT(func)标识核心系统服务的初始化启动入口。
    SYS_FEATURE_INIT(func)标识核心系统功能的初始化启动入口。
    APP_SERVICE_INIT(func)标识应用层服务的初始化启动入口。
    APP_FEATURE_INIT(func)标识应用层功能的初始化启动入口。
    开发实例

    服务自动初始化宏使用实例:

    void SystemServiceInit(void) {
        printf("Init System Service\n");
    }
    SYS_SERVICE_INIT(SystemServiceInit);
    
    void SystemFeatureInit(void) {
        printf("Init System Feature\n");
    }
    SYS_FEATURE_INIT(SystemFeatureInit);
    
    void AppServiceInit(void) {
        printf("Init App Service\n");
    }
    APP_SERVICE_INIT(AppServiceInit);
    
    void AppFeatureInit(void) {
        printf("Init App Feature\n");
    }
    APP_FEATURE_INIT(AppFeatureInit);
    
    // 日志打印顺序为:
    // Init System Service
    // Init System Feature
    // Init App Service
    // Init App Feature
    

启动引导OpenHarmony标准系统的详细流程

当前OpenHarmony标准系统默认支持以下几个镜像:

镜像名称挂载点说明
boot.imgNA内核和ramdisk镜像,bootloader加载的第一个镜像
system.img/system系统组件镜像,存放与芯片方案无关的平台业务
vendor.img/vendor芯片组件镜像,存放芯片相关的硬件抽象服务
updater.img/升级组件镜像,用于完成升级;正常启动时不加载次镜像
userdata.img/data可写的用户数据镜像

每个开发板都需要在存储器上划分好分区来存放上述镜像,SOC启动时都由bootloader来加载这些镜像,具体过程包括以下几个大的步骤:

  • bootloader初始化ROM和RAM等硬件,加载分区表信息。
  • bootloader根据分区表加载boot.img,从中解析并加载ramdisk.img到内存中。
  • bootloader准备好分区表信息,ramdisk地址等信息,进入内核,内核加载ramdisk并执行init。
  • init准备初始文件系统,挂载required.fstab(包括system.imgvendor.img的挂载)。
  • 扫描system.imgvendor.imgetc/init目录下的启动配置脚本,执行各个启动命令。

u-boot启动

  • u-boot加载

    支持了ramdisk的启动过程,此场景需要修改productdefine中的产品配置文件,通过"enable_ramdisk"开关开启ramdisk生成,这一部分与平台相关,不同的平台对于ramdisk的处理方式不一样。以Hi3516DV300平台为例,需要将u-boot中的原启动参数修改为root=/dev/ram0 initrd=0x84000000,0x292e00


uboot引导内核启动

  • u-boot进入

    u-boot启动进入内核时,可以通过bootargs传递关键信息给内核,这一部分内容是与平台相关的,主要信息如下:

    名称示例说明
    initrd0x84000000,0x292e00参考内核文档。
    ramfs-rootfs-initramfs.rst
    initrd.rst
    init/init
    blkdevpartsmmcblk0:1M(boot),15M(kernel),200M(system),200M(vendor),
    2M(misc),20M(updater),-(userdata)
    分区表信息,kernel会根据此信息创建物理分区。
    hardwareHi3516DV300、rk3568等(必要信息)硬件平台。
    root/dev/ram0(Hi3516DV00)、root=PARTUUID=614e0000-0000 rw(rk3568)kernel加载的启动设备。
    rootfstypeext4根文件系统类型。
    default_boot_devicesoc/10100000.himci.eMMC(建议配置信息)默认启动设备,在启动第一阶段会根据这个参数创建required设备的软链接。
    ohos.required_mount.xxx/dev/block/platform/soc/10100000.himci.eMMC/by-name/xxx@/usr@ext4@ro,barrier=1@wait,required现支持从cmdline中读取fstab信息,获取失败的情况下,会继续尝试从fstab.required文件中读取

内核启动流程图
在这里插入图片描述


启动框架层级

层级说明
LOS_INIT_LEVEL_EARLIEST最早期初始化
说明:不依赖架构,单板以及后续模块会对其有依赖的纯软件模块初始化
例如:Trace模块
LOS_INIT_LEVEL_ARCH_EARLY架构早期初始化
说明:架构相关,后续模块会对其有依赖的模块初始化,如启动过程中非必需的功能,建议放到LOS_INIT_LEVEL_ARCH层
LOS_INIT_LEVEL_PLATFORM_EARLY平台早期初始化
说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化,如启动过程中必需的功能,建议放到LOS_INIT_LEVEL_PLATFORM层
例如:uart模块
LOS_INIT_LEVEL_KMOD_PREVM内存初始化前的内核模块初始化
说明:在内存初始化之前需要使能的模块初始化
LOS_INIT_LEVEL_VM_COMPLETE基础内存就绪后的初始化
说明:此时内存初始化完毕,需要进行使能且不依赖进程间通讯机制与系统进程的模块初始化
例如:共享内存功能
LOS_INIT_LEVEL_ARCH架构后期初始化
说明:架构拓展功能相关,后续模块会对其有依赖的模块初始化
LOS_INIT_LEVEL_PLATFORM平台后期初始化
说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化
例如:驱动内核抽象层初始化(mmc、mtd)
LOS_INIT_LEVEL_KMOD_BASIC内核基础模块初始化
说明:内核可拆卸的基础模块初始化
例如:VFS初始化
LOS_INIT_LEVEL_KMOD_EXTENDED内核扩展模块初始化
说明:内核可拆卸的扩展模块初始化
例如:系统调用初始化、ProcFS初始化、Futex初始化、HiLog初始化、HiEvent初始化、LiteIPC初始化
LOS_INIT_LEVEL_KMOD_TASK内核任务创建
说明:进行内核任务的创建(内核任务,软件定时器任务)
例如:资源回收系统常驻任务的创建、SystemInit任务创建、CPU占用率统计任务创建
LOS_INIT_LEVEL_FINISH内核初始化完成

汇编阶段(LiteOS-A内核)

uboot引导LiteOS-A启动入口:
kernel\liteos_a\tools\build\liteos.ld

ENTRY(reset_vector)
INCLUDE board.ld
SECTIONS
{
     _start = .;
    .set_sysinit_set : {
        __start_set_sysinit_set = ABSOLUTE(.);
        KEEP (*(.set_sysinit_set))
        __stop_set_sysinit_set = ABSOLUTE(.);
    } > ram
    .
    .
    .
}

reset_vector就是整个鸿蒙内核启动入口点,这是个符号,定义在:
kernel\liteos_a\arch\arm\arm\src\startup\reset_vector_mp.S, 这个文件是多核使用的,同目录下的reset_vector_up.S是单核使用的。

    bl     main

_start_hang:
    b      _start_hang

通过main函数进入内核的C语言阶段

c语言阶段(LiteOS-A内核)

kernel\liteos_a\kernel\common\main.c

/**
 * @brief 
 * 内核入口函数,由汇编调用,见于reset_vector_up.S 和 reset_vector_mp.S 
 * up指单核CPU, mp指多核CPU bl        main
 * @return LITE_OS_SEC_TEXT_INIT 
 */
LITE_OS_SEC_TEXT_INIT INT32 main(VOID)//由主CPU执行,默认0号CPU 为主CPU 
{
    UINT32 ret = OsMain();
    if (ret != LOS_OK) {
        return (INT32)LOS_NOK;
    }

    CPU_MAP_SET(0, OsHwIDGet());//设置主CPU映射信息

    OsSchedStart();//调度开始

    while (1) {
        __asm volatile("wfi");//WFI: wait for Interrupt 等待中断,即下一次中断发生前都在此hold住不干活
    }
}

kernel\liteos_a\kernel\common\los_config.c

///由汇编调用,鸿蒙C语言层级的入口点 
LITE_OS_SEC_TEXT_INIT UINT32 OsMain(VOID)
{
    UINT32 ret;
#ifdef LOS_INIT_STATISTICS
    UINT64 startNsec, endNsec, durationUsec;
#endif

    ret = EarliestInit();//鸿蒙初开,天地混沌
    if (ret != LOS_OK) {
        return ret;
    }
    OsInitCall(LOS_INIT_LEVEL_EARLIEST);

    ret = ArchEarlyInit(); //架构级初始化,包括硬中断
    if (ret != LOS_OK) {
        return ret;
    }
    OsInitCall(LOS_INIT_LEVEL_ARCH_EARLY);

    ret = PlatformEarlyInit();//平台级初始化
    if (ret != LOS_OK) {
        return ret;
    }
    OsInitCall(LOS_INIT_LEVEL_PLATFORM_EARLY);

    /* system and chip info */
    OsSystemInfo();

    PRINT_RELEASE("\nmain core booting up...\n");

#ifdef LOS_INIT_STATISTICS
    startNsec = LOS_CurrNanosec();
#endif

    //进程模块初始化
    ret = OsProcessInit();
    if (ret != LOS_OK) {
        return ret;
    }

    OsInitCall(LOS_INIT_LEVEL_KMOD_PREVM);

    ret = OsSysMemInit();//系统内存初始化
    if (ret != LOS_OK) {
        return ret;
    }

    OsInitCall(LOS_INIT_LEVEL_VM_COMPLETE);

    ret = OsIpcInit();//进程间通讯模块初始化
    if (ret != LOS_OK) {
        return ret;
    }

    ret = OsSystemProcessCreate();//创建系统进程 
    if (ret != LOS_OK) {
        return ret;
    }

    ret = ArchInit();	//MMU架构初始化
    if (ret != LOS_OK) {
        return ret;
    }
    OsInitCall(LOS_INIT_LEVEL_ARCH);

    ret = PlatformInit();
    if (ret != LOS_OK) {
        return ret;
    }
    OsInitCall(LOS_INIT_LEVEL_PLATFORM);

    ret = KModInit();
    if (ret != LOS_OK) {
        return ret;
    }

    OsInitCall(LOS_INIT_LEVEL_KMOD_BASIC);

    OsInitCall(LOS_INIT_LEVEL_KMOD_EXTENDED);

#ifdef LOSCFG_KERNEL_SMP
    OsSmpInit();
#endif

    OsInitCall(LOS_INIT_LEVEL_KMOD_TASK);

#ifdef LOS_INIT_STATISTICS
    endNsec = LOS_CurrNanosec();
    durationUsec = (endNsec - startNsec) / OS_SYS_NS_PER_US;
    PRINTK("The main core takes %lluus to start.\n", durationUsec);
#endif

    return LOS_OK;
}

......

/*! 进程模块初始化,被编译放在代码段 .init 中*/
UINT32 OsProcessInit(VOID)
{
    UINT32 index;
    UINT32 size;
    UINT32 ret;

    g_processMaxNum = LOSCFG_BASE_CORE_PROCESS_LIMIT;//默认支持64个进程
    size = (g_processMaxNum + 1) * sizeof(LosProcessCB);

    g_processCBArray = (LosProcessCB *)LOS_MemAlloc(m_aucSysMem1, size);// 进程池,占用内核堆,内存池分配 
    if (g_processCBArray == NULL) {
        return LOS_NOK;
    }
    (VOID)memset_s(g_processCBArray, size, 0, size);//安全方式重置清0

    LOS_ListInit(&g_freeProcess);//进程空闲链表初始化,创建一个进程时从g_freeProcess中申请一个进程描述符使用
    LOS_ListInit(&g_processRecycleList);//进程回收链表初始化,回收完成后进入g_freeProcess等待再次被申请使用

    for (index = 0; index < g_processMaxNum; index++) {//进程池循环创建
        g_processCBArray[index].processID = index;//进程ID[0-g_processMaxNum-1]赋值
        g_processCBArray[index].processStatus = OS_PROCESS_FLAG_UNUSED;// 默认都是白纸一张,贴上未使用标签
        LOS_ListTailInsert(&g_freeProcess, &g_processCBArray[index].pendList);//注意g_freeProcess挂的是pendList节点,所以使用要通过OS_PCB_FROM_PENDLIST找到进程实体.
    }

    /* Default process to prevent thread PCB from being empty */
    g_processCBArray[index].processID = index;
    g_processCBArray[index].processStatus = OS_PROCESS_FLAG_UNUSED;

    ret = OsTaskInit((UINTPTR)&g_processCBArray[g_processMaxNum]);
    if (ret != LOS_OK) {
        (VOID)LOS_MemFree(m_aucSysMem1, g_processCBArray);
        return LOS_OK;
    }

#ifdef LOSCFG_KERNEL_CONTAINER
    OsInitRootContainer();
#endif
#ifdef LOSCFG_KERNEL_PLIMITS
    OsProcLimiterSetInit();
#endif
    SystemProcessEarlyInit(OsGetIdleProcess());//初始化 0,1,2号进程
    SystemProcessEarlyInit(OsGetUserInitProcess());
    SystemProcessEarlyInit(OsGetKernelInitProcess());
    return LOS_OK;
}
.
.
.
.
.
.
#ifndef LOSCFG_PLATFORM_ADAPT
STATIC VOID SystemInit(VOID)
{
    PRINTK("dummy: *** %s ***\n", __FUNCTION__);
}
#else
extern VOID SystemInit(VOID);
#endif
#ifndef LOSCFG_ENABLE_KERNEL_TEST
///创建系统初始任务并申请调度
STATIC UINT32 OsSystemInitTaskCreate(VOID)
{
    UINT32 taskID;
    TSK_INIT_PARAM_S sysTask;

    (VOID)memset_s(&sysTask, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
    sysTask.pfnTaskEntry = (TSK_ENTRY_FUNC)SystemInit;//任务入口函数
    sysTask.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;//16k
    sysTask.pcName = "SystemInit";//任务名称
    sysTask.usTaskPrio = LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO;//内核默认优先级10
    sysTask.uwResved = LOS_TASK_STATUS_DETACHED;//任务分离模式
#ifdef LOSCFG_KERNEL_SMP
    sysTask.usCpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid());
#endif
    return LOS_TaskCreate(&taskID, &sysTask);
}

//系统任务初始化
STATIC UINT32 OsSystemInit(VOID)
{
    UINT32 ret;

    ret = OsSystemInitTaskCreate();
    if (ret != LOS_OK) {
        return ret;
    }

    return 0;
}

//在内核初始化的时候初始化该模块,则通过内核启动框架将该模块的初始化函数注册进内核启动流程
LOS_MODULE_INIT(OsSystemInit, LOS_INIT_LEVEL_KMOD_TASK);//模块初始化
#endif

通过上述调用最终调用到SystemInit任务,跳转到soc的SystemInit()做系统初始化。
device\soc\hisilicon\hi3516dv300\sdk_liteos\mpp\module_init\src\system_init.c

void SystemInit(void)
{
    SystemInit_QuickstartInit();

    SystemInit_IPCM();
    SystemInit_RandomInit();
    SystemInit_MMCInit();
    SystemInit_MemDevInit();
    SystemInit_GpioDevInit();
    SystemInit_SDKInit();
    SystemInit_HDFInit();
    SystemInit_NetInit();  /* need to check later */
    SystemInit_MountRootfs();
    SystemInit_ConsoleInit();
#ifndef LOSCFG_DRIVERS_QUICKSTART
    SystemInit1();
    SystemInit2();
    SystemInit3();
#endif
    SystemInit_UserInitProcess();
}


void SystemInit_UserInitProcess(void)
{
    if (OsUserInitProcess()) {//跳转回到内核创建1号init进程
        PRINT_ERR("Create user init process faialed!\n");
        return;
    }
    return;
}

kernel\liteos_a\kernel\base\core\los_process.c

LITE_OS_SEC_TEXT_INIT UINT32 OsUserInitProcess(VOID)
{
    UINT32 ret;
    UINT32 size;
    TSK_INIT_PARAM_S param = { 0 };
    VOID *stack = NULL;

    //获取用户态进程的根进程,所有用户进程都是g_processCBArray[g_userInitProcess] fork来的
    LosProcessCB *processCB = OsGetUserInitProcess();
    ret = OsSystemProcessInit(processCB, OS_USER_MODE, "Init");// 进程创建初始化
    if (ret != LOS_OK) {
        return ret;
    }

    ret = OsLoadUserInit(processCB);
    if (ret != LOS_OK) {
        goto ERROR;
    }

    stack = OsUserInitStackAlloc(processCB, &size);//初始化堆栈区,分配栈内存
    if (stack == NULL) {
        PRINT_ERR("Alloc user init process user stack failed!\n");
        goto ERROR;
    }

    //代码区开始位置,对应LITE_USER_SEC_ENTRY
    param.pfnTaskEntry = (TSK_ENTRY_FUNC)(CHAR *)&__user_init_entry;
    param.userParam.userSP = (UINTPTR)stack + size;//指向栈顶
    param.userParam.userMapBase = (UINTPTR)stack;//栈底
    param.userParam.userMapSize = size;//栈大小
    param.uwResved = OS_TASK_FLAG_PTHREAD_JOIN;//能够被其他线程收回其资源和啥事
    ret = OsUserInitProcessStart(processCB, &param);//用户进程开始初始化
    if (ret != LOS_OK) {
        (VOID)OsUnMMap(processCB->vmSpace, param.userParam.userMapBase, param.userParam.userMapSize);
        goto ERROR;
    }

    return LOS_OK;

ERROR:
    OsDeInitPCB(processCB);
    return ret;
}


STATIC UINT32 OsUserInitProcessStart(LosProcessCB *processCB, TSK_INIT_PARAM_S *param)
{
    UINT32 intSave;
    INT32 ret;

    UINT32 taskID = OsCreateUserTask((UINTPTR)processCB, param);
    if (taskID == OS_INVALID_VALUE) {
        return LOS_NOK;
    }

    //设置进程优先级
    ret = LOS_SetProcessPriority(processCB->processID, OS_PROCESS_USERINIT_PRIORITY);
    if (ret != LOS_OK) {
        PRINT_ERR("User init process set priority failed! ERROR:%d \n", ret);
        goto EXIT;
    }

    SCHEDULER_LOCK(intSave);
    processCB->processStatus &= ~OS_PROCESS_STATUS_INIT;
    SCHEDULER_UNLOCK(intSave);

    //调度器:设置为抢占式调度和最低任务优先级(31级)
    ret = LOS_SetTaskScheduler(taskID, LOS_SCHED_RR, OS_TASK_PRIORITY_LOWEST);
    if (ret != LOS_OK) {
        PRINT_ERR("User init process set scheduler failed! ERROR:%d \n", ret);
        goto EXIT;
    }

    return LOS_OK;

EXIT:
    (VOID)LOS_TaskDelete(taskID);
    return ret;
}

__user_init_entry在编译链接文件
kernel\liteos_a\tools\build\liteos.ld 中

.user_init USER_INIT_VM_START : ALIGN(0x1000) {
        . = ALIGN(0x4);
        __user_init_load_addr = LOADADDR(.user_init);
        __user_init_entry = .;
        KEEP(libuserinit.O (.user.entry))//地址指向镜像的.user.entry
        KEEP(libuserinit.O (.user.text))
        KEEP(libuserinit.O (.user.rodata))
        . = ALIGN(0X4);
        __user_init_data = .;
        KEEP(libuserinit.O (.user.data))
        . = ALIGN(0X4);
        __user_init_bss = .;
        KEEP(libuserinit.O (.user.bss))
        . = ALIGN(0x1000);
        __user_init_end = .;
    } > user_ram AT > ram

.user.entry通过宏定义在
kernel\liteos_a\kernel\user\include\los_user_init.h中

#ifndef LITE_USER_SEC_TEXT
#define LITE_USER_SEC_TEXT   __attribute__((section(".user.text")))
#endif

#ifndef LITE_USER_SEC_ENTRY
#define LITE_USER_SEC_ENTRY   __attribute__((section(".user.entry")))
#endif

#ifndef LITE_USER_SEC_DATA
#define LITE_USER_SEC_DATA   __attribute__((section(".user.data")))
#endif

#ifndef LITE_USER_SEC_RODATA
#define LITE_USER_SEC_RODATA   __attribute__((section(".user.rodata")))
#endif

#ifndef LITE_USER_SEC_BSS
#define LITE_USER_SEC_BSS   __attribute__((section(".user.bss")))
#endif

init进程启动进入函数OsUserInit
kernel\liteos_a\kernel\user\src\los_user_init.c

#ifdef LOSCFG_QUICK_START
LITE_USER_SEC_RODATA STATIC CHAR *g_initPath = "/dev/shm/init";
#else
LITE_USER_SEC_RODATA STATIC CHAR *g_initPath = "/bin/init";//由Init_lite在编译后,生成
#endif
///将 sys_call3 链接在 section(".user.text")段
LITE_USER_SEC_TEXT STATIC UINT32 sys_call3(UINT32 nbr, UINT32 parm1, UINT32 parm2, UINT32 parm3)
{
    register UINT32 reg7 __asm__("r7") = (UINT32)(nbr); //系统调用号给了R7寄存器
    register UINT32 reg2 __asm__("r2") = (UINT32)(parm3);//R2 = 参数3
    register UINT32 reg1 __asm__("r1") = (UINT32)(parm2);//R1 = 参数2
    register UINT32 reg0 __asm__("r0") = (UINT32)(parm1);//R0 = 参数1
    
	//SVC指令会触发一个特权调用异常。这为非特权软件调用操作系统或其他只能在PL1级别访问的系统组件提供了一种机制。
    __asm__ __volatile__
    (
        "svc %1" //管理模式(svc)      [10011]:操作系统使用的保护模式
        : "=r"(reg0)	//输出寄存器为R0
        : "i"(SYS_CALL_VALUE), "r"(reg7), "r"(reg0), "r"(reg1), "r"(reg2)
        : "memory", "r14"
    );
	//相当于执行了 reset_vector_mp.S 中的 向量表0x08对应的 _osExceptSwiHdl 
    return reg0;//reg0的值将在汇编中改变.
}

LITE_USER_SEC_ENTRY VOID OsUserInit(VOID *args)
{
#ifdef LOSCFG_KERNEL_DYNLOAD
    sys_call3(__NR_execve, (UINTPTR)g_initPath, 0, 0);//发起系统调用,陷入内核态,对应 SysExecve ,加载elf运行
#endif
    while (true) {
    }
}
#endif

最终启动了/bin/init可执行程序

标准linux内核

kernel\linux\linux-5.10\init\main.c

各种模块的初始化
asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
{
	char *command_line;
	char *after_dashes;

	set_task_stack_end_magic(&init_task);
	smp_setup_processor_id();
	debug_objects_early_init();

	cgroup_init_early();

	local_irq_disable();
	early_boot_irqs_disabled = true;

	/*
	 * Interrupts are still disabled. Do necessary setups, then
	 * enable them.
	 */
	boot_cpu_init();
	page_address_init();
	pr_notice("%s", linux_banner);
	early_security_init();
	setup_arch(&command_line);
	setup_boot_config(command_line);
	setup_command_line(command_line);
	setup_nr_cpu_ids();
	setup_per_cpu_areas();
	smp_prepare_boot_cpu();	/* arch-specific boot-cpu hooks */
	boot_cpu_hotplug_init();

	build_all_zonelists(NULL);
	page_alloc_init();

	pr_notice("Kernel command line: %s\n", saved_command_line);
	/* parameters may set static keys */
	jump_label_init();
	parse_early_param();
	after_dashes = parse_args("Booting kernel",
				  static_command_line, __start___param,
				  __stop___param - __start___param,
				  -1, -1, NULL, &unknown_bootoption);
	if (!IS_ERR_OR_NULL(after_dashes))
		parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,
			   NULL, set_init_arg);
	if (extra_init_args)
		parse_args("Setting extra init args", extra_init_args,
			   NULL, 0, -1, -1, NULL, set_init_arg);

	/*
	 * These use large bootmem allocations and must precede
	 * kmem_cache_init()
	 */
	setup_log_buf(0);
	vfs_caches_init_early();
	sort_main_extable();
	trap_init();
	mm_init();

	ftrace_init();

	/* trace_printk can be enabled here */
	early_trace_init();

	/*
	 * Set up the scheduler prior starting any interrupts (such as the
	 * timer interrupt). Full topology setup happens at smp_init()
	 * time - but meanwhile we still have a functioning scheduler.
	 */
	sched_init();

	if (WARN(!irqs_disabled(),
		 "Interrupts were enabled *very* early, fixing it\n"))
		local_irq_disable();
	radix_tree_init();

	/*
	 * Set up housekeeping before setting up workqueues to allow the unbound
	 * workqueue to take non-housekeeping into account.
	 */
	housekeeping_init();

	/*
	 * Allow workqueue creation and work item queueing/cancelling
	 * early.  Work item execution depends on kthreads and starts after
	 * workqueue_init().
	 */
	workqueue_init_early();

	rcu_init();

	/* Trace events are available after this */
	trace_init();

	if (initcall_debug)
		initcall_debug_enable();

	context_tracking_init();
	/* init some links before init_ISA_irqs() */
	early_irq_init();
	init_IRQ();
	tick_init();
	rcu_init_nohz();
	init_timers();
	hrtimers_init();
	softirq_init();
	timekeeping_init();
	time_init();

	/*
	 * For best initial stack canary entropy, prepare it after:
	 * - setup_arch() for any UEFI RNG entropy and boot cmdline access
	 * - timekeeping_init() for ktime entropy used in random_init()
	 * - time_init() for making random_get_entropy() work on some platforms
	 * - random_init() to initialize the RNG from from early entropy sources
	 */
	random_init(command_line);
	boot_init_stack_canary();

	perf_event_init();
	profile_init();
	call_function_init();
	WARN(!irqs_disabled(), "Interrupts were enabled early\n");

	early_boot_irqs_disabled = false;
	local_irq_enable();

	kmem_cache_init_late();

	/*
	 * HACK ALERT! This is early. We're enabling the console before
	 * we've done PCI setups etc, and console_init() must be aware of
	 * this. But we do want output early, in case something goes wrong.
	 */
	console_init();
	if (panic_later)
		panic("Too many boot %s vars at `%s'", panic_later,
		      panic_param);

	lockdep_init();

	/*
	 * Need to run this when irqs are enabled, because it wants
	 * to self-test [hard/soft]-irqs on/off lock inversion bugs
	 * too:
	 */
	locking_selftest();

	/*
	 * This needs to be called before any devices perform DMA
	 * operations that might use the SWIOTLB bounce buffers. It will
	 * mark the bounce buffers as decrypted so that their usage will
	 * not cause "plain-text" data to be decrypted when accessed.
	 */
	mem_encrypt_init();

#ifdef CONFIG_BLK_DEV_INITRD
	if (initrd_start && !initrd_below_start_ok &&
	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
		pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.\n",
		    page_to_pfn(virt_to_page((void *)initrd_start)),
		    min_low_pfn);
		initrd_start = 0;
	}
#endif
	setup_per_cpu_pageset();
	numa_policy_init();
	acpi_early_init();
	if (late_time_init)
		late_time_init();
	sched_clock_init();
	calibrate_delay();
	pid_idr_init();
	anon_vma_init();
#ifdef CONFIG_X86
	if (efi_enabled(EFI_RUNTIME_SERVICES))
		efi_enter_virtual_mode();
#endif
	thread_stack_cache_init();
	cred_init();
	fork_init();
	proc_caches_init();
	uts_ns_init();
	buffer_init();
	key_init();
	security_init();
	dbg_late_init();
	vfs_caches_init();
	pagecache_init();
	signals_init();
	seq_file_init();
	proc_root_init();
	nsfs_init();
	cpuset_init();
	cgroup_init();
	taskstats_init_early();
	delayacct_init();
#ifdef CONFIG_RECLAIM_ACCT
	reclaimacct_init();
#endif

	poking_init();
	check_bugs();

	acpi_subsystem_init();
	arch_post_acpi_subsys_init();
	sfi_init_late();
	kcsan_init();

	/* Do the rest non-__init'ed, we're now alive */
	arch_call_rest_init();

	prevent_tail_call_optimization();
}
.
.
.
.
.
void __init __weak arch_call_rest_init(void)
{
	rest_init();
}

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.
	 */
     启动1号进程init
	pid = kernel_thread(kernel_init, NULL, CLONE_FS);
	/*
	 * Pin init on the boot CPU. Task migration is not properly working
	 * until sched_init_smp() has been run. It will set the allowed
	 * CPUs for init to the non isolated CPUs.
	 */
	rcu_read_lock();
	tsk = find_task_by_pid_ns(pid, &init_pid_ns);
	set_cpus_allowed_ptr(tsk, cpumask_of(smp_processor_id()));
	rcu_read_unlock();

	numa_default_policy();
	pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
	rcu_read_lock();
	kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
	rcu_read_unlock();

	/*
	 * Enable might_sleep() and smp_processor_id() checks.
	 * They cannot be enabled earlier because with CONFIG_PREEMPTION=y
	 * kernel_thread() would trigger might_sleep() splats. With
	 * CONFIG_PREEMPT_VOLUNTARY=y the init task might have scheduled
	 * already, but it's stuck on the kthreadd_done completion.
	 */
	system_state = SYSTEM_SCHEDULING;

	complete(&kthreadd_done);

	/*
	 * The boot idle thread must execute schedule()
	 * at least once to get things moving:
	 */
	schedule_preempt_disabled();
	/* Call into cpu_idle with preempt disabled */
	cpu_startup_entry(CPUHP_ONLINE);
}

.
.
.
.
.
.
static int __ref kernel_init(void *unused)
{
	int ret;

	kernel_init_freeable();
	/* need to finish all async __init code before freeing the memory */
	async_synchronize_full();
	kprobe_free_init_mem();
	ftrace_free_init_mem();
	kgdb_free_init_mem();
	free_initmem();
	mark_readonly();

	/*
	 * Kernel mappings are now finalized - update the userspace page-table
	 * to finalize PTI.
	 */
	pti_finalize();

	system_state = SYSTEM_RUNNING;
	numa_default_policy();

	rcu_end_inkernel_boot();

	do_sysctl_args();

	if (ramdisk_execute_command) {
		ret = run_init_process(ramdisk_execute_command);
		if (!ret)
			return 0;
		pr_err("Failed to execute %s (error %d)\n",
		       ramdisk_execute_command, ret);
	}

	/*
	 * We try each of these until one succeeds.
	 *
	 * The Bourne shell can be used instead of init if we are
	 * trying to recover a really broken machine.
	 */
	if (execute_command) {
		ret = run_init_process(execute_command);
		if (!ret)
			return 0;
		panic("Requested init %s failed (error %d).",
		      execute_command, ret);
	}

	if (CONFIG_DEFAULT_INIT[0] != '\0') {
		ret = run_init_process(CONFIG_DEFAULT_INIT);
		if (ret)
			pr_err("Default init %s failed (error %d)\n",
			       CONFIG_DEFAULT_INIT, ret);
		else
			return 0;
	}

    //最终启动了/bin/init可执行程序,同liteos-a  
	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.");
}

init进程 (标准系统)

通过BUILD.gn可知如下路径代码编译成了可执行程序init
base\startup\init\services\init\standard\BUILD.gn

ohos_executable("init") {
  sources = [
    "../adapter/init_adapter.c",
    "../standard/device.c",
    "../standard/fd_holder_service.c",
    "../standard/init.c",
    "../standard/init_cmdexecutor.c",
    "../standard/init_cmds.c",
    "../standard/init_control_fd_service.c",
    "../standard/init_firststage.c",
    "../standard/init_jobs.c",
    "../standard/init_mount.c",
    "../standard/init_reboot.c",
    "../standard/init_service.c",
    "../standard/init_signal_handler.c",
    "../standard/switch_root.c",
    "bootstagehooker.c",
  ]
  ......
}

从init进程main函数开始
base\startup\init\services\init\main.c

static const pid_t INIT_PROCESS_PID = 1;

int main(int argc, char * const argv[])
{
    const char *uptime = NULL;
    long long upTimeInMicroSecs = 0;
    int isSecondStage = 0;
    //在接收到SIGPIPE信号时,设置成SIG_IGN忽略信号,不会中断程序执行,而是继续执行后续操作
    (void)signal(SIGPIPE, SIG_IGN);
    // Number of command line parameters is 2
    //从kernel启动的init进程不会携带任何参数,从StartInitSecondStage启动的init进程第二阶段会携带参数
    if (argc > 1 && (strcmp(argv[1], "--second-stage") == 0)) {
        isSecondStage = 1;
        if (argc > 2) {
            uptime = argv[2];
        }
    } else {
        upTimeInMicroSecs = GetUptimeInMicroSeconds(NULL);
    }
    //正常启动init进程的pid为1
    if (getpid() != INIT_PROCESS_PID) {
        INIT_LOGE("Process id error %d!", getpid());
        return 0;
    }
    //使能init阶段log
    EnableInitLog(INIT_INFO);

    // Updater mode
    if (isSecondStage == 0) {
        //从kernel启动的init第一阶段走如下:
        SystemPrepare(upTimeInMicroSecs);
    } else {
        //初始化kmsg
        LogInit();
    }

    SystemInit();//执行init进程的初始化,注册socket

    SystemExecuteRcs();//执行Linux的初始化(rcs进程)

    SystemConfig(uptime);//1. 读取cfg配置文件内容(根据是否重启计重启原因加载不同的cfg配置),扫描各个系统的启动脚本,解析jobs的pre-init,init,post-init合并到一起存储在/etc/init.cfg中(其他自命名的job默认在post-init阶段执行)
    2. 解析services配置,获取要初始化服务的path、uid、gid等信息(/foundation,/appspawn等服务)
    3. 最后通过trigger依次执行这些操作,执行如创建文件夹,文件授权等cmd操作和start service的操作

    SystemRun();//创建一个LoopEvent处理事件,通过epoll实现,运行启动service服务
    return 0;
}

base\startup\init\services\init\standard\init_firststage.c

void SystemPrepare(long long upTimeInMicroSecs)
{
    (void)signal(SIGPIPE, SIG_IGN);

    EnableInitLog(INIT_INFO);
    EarlyLogInit();
    INIT_LOGI("Start init first stage.");

    //挂载一些目录创建一些设备节点,打开/proc/sys/kernel/printk_devkmsg文件
    //base\startup\init\services\init\standard\device.c
    CreateFsAndDeviceNode();

    //钩子函数 插桩
    //base\startup\init\interfaces\innerkits\hookmgr\hookmgr.c
    HookMgrExecute(GetBootStageHookMgr(), INIT_FIRST_STAGE, NULL, NULL);

    // Updater mode no need to mount and switch root
    //升级模式不进入第二阶段
    if (InUpdaterMode() != 0) {
        return;
    }

    //挂载required分区
    MountRequiredPartitions();

    //二级启动init
    StartSecondStageInit(upTimeInMicroSecs);
}
.
.
.
int InUpdaterMode(void)
{
    const char * const updaterExecutabeFile = "/bin/updater";
    if (access(updaterExecutabeFile, X_OK) == 0) { //判断/bin/updater文件是否有执行权限,由于文件不存在,所以不可能为0,那么此函数的返回值为0.
        return 1;
    } else {
        return 0;
    }
}
.
.
.
static void MountRequiredPartitions(void)
{
    int requiredNum = 0;
    //获取required分区信息
    Fstab *fstab = LoadRequiredFstab();
    char **devices = (fstab != NULL) ? GetRequiredDevices(*fstab, &requiredNum) : NULL;
    if (devices != NULL && requiredNum > 0) {
        //创建socket,触发内核上报uevent事件
        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;
    }
}

static void StartSecondStageInit(long long uptime)
{
    INIT_LOGI("Start init second stage.");
    // It will panic if close stdio before execv("/bin/sh", NULL)
    CloseStdio();

    SwitchRoot("/usr");
    char buf[64];
    snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%lld", uptime);
    // Execute init second stage
    char * const args[] = {
        "/bin/init",
        "--second-stage",
        buf,
        NULL,
    };
    if (execv("/bin/init", args) != 0) {
        INIT_LOGE("Failed to exec \"/bin/init\", err = %d", errno);
        exit(-1);
    }
}
  • init挂载required分区 (详情介绍见:init进程挂载ruquired分区.md)

    所谓required分区,就是系统启动引导过程的必要分区,必须在二级启动开始前进行挂载。比如system、vendor等必选镜像,挂载这些镜像前,需要先创建对应的块设备文件。这些块设备文件是通过内核上报UEVENT事件来创建的。init需要知道存储器的主设备目录,需要bootloader通过default_boot_device传递。

    目前init支持两种方式获取required分区信息,一是通过保存在/proc/cmdline中的bootargs,init会首先尝试从cmdline读取required分区信息;二是通过读取ramdisk中的fstab.required文件,只有在前一种方式获取失败的情况下才会尝试通过这种方式获取。

    • 块设备的创建逻辑

      • 准备工作

        1. init从cmdline中读取required fstab,若获取失败,则尝试读fstab.required文件,从中获取必须挂载的块设备的PARTNAME,例如system和vendor.
        2. 创建接收内核上报uevent事件广播消息的socket,从/proc/cmdline里读取default_boot_device。
        3. 带着fstab信息和socket句柄遍历/sys/devices目录,准备开始触发内核上报uevent事件。
      • 触发事件

        1. 通过ueventd触发内核上报uevent事件
        2. 匹配uevent事件中的partitionName与required fstab中的device信息。
        3. 匹配成功后将会进一步处理,格式化设备节点路径,准备开始创建设备节点。
      • 创建节点

        1. 为了便于用户态下对设备节点的访问以及提高设备节点的可读性,会对即将创建的required块设备节点同时创建软链接,这就需要先格式化软链接的路径。
        2. 以上工作都完成后,将执行最后的创建设备节点的步骤,根据传入的uevent中的主次设备号、前置步骤中构建的设备节点路径和软链接路径等创建设备节点,并创建相应软链接。

      至此,块设备节点创建完毕。

    • 与default_boot_device匹配关系

      内核将bootargs信息写入/proc/cmdline,其中就包含了default_boot_device,这个值是内核当中约定好的系统启动必要的主设备目录。以ohos.required_mount.为前缀的内容则是系统启动必要的分区挂载信息,其内容与fstab.required文件内容应当是一致的。另外,分区挂载信息中的块设备节点就是default_boot_device目录中by-name下软链接指向的设备节点。例如,default_boot_device的值为soc/10100000.himci.eMMC,那么ohos.required_mount.system的值就包含了/dev/block/platform/soc/10100000.himci.eMMC/by-name/system这个指向system设备节点的软链接路径。

      在创建块设备节点的过程中,会有一个将设备路径与default_boot_device的值匹配的操作,匹配成功后,会在/dev/block/by-name目录下创建指向真实块设备节点的软链接,以此在访问设备节点的过程中实现芯片平台无关化。

通过StartSecondStageInit函数开始init进程启动的第二阶段
base\startup\init\services\init\main.c

static const pid_t INIT_PROCESS_PID = 1;

int main(int argc, char * const argv[])
{
    const char *uptime = NULL;
    long long upTimeInMicroSecs = 0;
    int isSecondStage = 0;
    //在接收到SIGPIPE信号时,设置成SIG_IGN忽略信号,不会中断程序执行,而是继续执行后续操作
    (void)signal(SIGPIPE, SIG_IGN);
    // Number of command line parameters is 2
    //从kernel启动的init进程不会携带任何参数,从StartInitSecondStage启动的init进程第二阶段会携带参数
    if (argc > 1 && (strcmp(argv[1], "--second-stage") == 0)) {
        isSecondStage = 1;
        if (argc > 2) {
            uptime = argv[2];
        }
    } else {
        upTimeInMicroSecs = GetUptimeInMicroSeconds(NULL);
    }
    //正常启动init进程的pid为1
    if (getpid() != INIT_PROCESS_PID) {
        INIT_LOGE("Process id error %d!", getpid());
        return 0;
    }
    //使能init阶段log
    EnableInitLog(INIT_INFO);

    // Updater mode
    if (isSecondStage == 0) {
        //从kernel启动的init第一阶段走如下:
        SystemPrepare(upTimeInMicroSecs);
    } else {
        //初始化kmsg
        LogInit();
    }

    SystemInit();//执行init进程的初始化,注册socket

    SystemExecuteRcs();//执行Linux的初始化(rcs进程)

    SystemConfig(uptime);//1. 读取cfg配置文件内容(根据是否重启计重启原因加载不同的cfg配置),扫描各个系统的启动脚本,解析jobs的pre-init,init,post-init合并到一起存储在/etc/init.cfg中(其他自命名的job默认在post-init阶段执行)
    2. 解析services配置,获取要初始化服务的path、uid、gid等信息(/foundation,/appspawn等服务)
    3. 最后通过trigger依次执行这些操作,执行如创建文件夹,文件授权等cmd操作和start service的操作

    SystemRun();//创建一个LoopEvent处理事件,通过epoll实现,运行启动service服务
    return 0;
}

由于第二阶段启动携带参数--second-stage,所以走到LogInit(),接着串行执行SystemInit();
base\startup\init\services\init\standard\init.c

void LogInit(void)
{
    //创建/dev/kmsg节点文件
    int ret = mknod("/dev/kmsg", S_IFCHR | S_IWUSR | S_IRUSR,
        makedev(MEM_MAJOR, DEV_KMSG_MINOR));
    if (ret == 0) {
        //打开节点文件/dev/kmsg
        OpenLogDevice();
    }
}
.
.
.
.
.
.
void SystemInit(void)
{
    CloseStdio();
#ifndef STARTUP_INIT_TEST
    // Set up a session keyring that all processes will have access to.
    //设置一个所有进程都可以访问的会话密钥环???
    //具体见foundation\filemanagement\storage_service\
    KeyCtrlGetKeyringId(KEY_SPEC_SESSION_KEYRING, 1);
#endif
    // umask call always succeeds and return the previous mask value which is not needed here
    //设置文件权限
    (void)umask(DEFAULT_UMASK_INIT);
    //递归赋予目录权限
    MakeDirRecursive("/dev/unix/socket", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
    int sock = FdHolderSockInit();
    if (sock >= 0) {
        RegisterFdHoldWatcher(sock);
    }
    InitControlFd();

    // sysclktz 0
    //设置系统时间
    struct timezone tz = { 0 };
    if (settimeofday(NULL, &tz) == -1) {
        INIT_LOGE("Set time of day failed, err = %d", errno);
    }
}
.
.
.
static int FdHolderSockInit(void)
{
    int sock = -1;
    int on = 1;
    int fdHolderBufferSize = FD_HOLDER_BUFFER_SIZE; // 4KiB
    //创建一个本地通信的socket,sock 是创建成功的套接字
    sock = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
    if (sock < 0) {
        INIT_LOGE("Failed to create fd holder socket, err = %d", errno);
        return -1;
    }

    setsockopt(sock, SOL_SOCKET, SO_RCVBUFFORCE, &fdHolderBufferSize, sizeof(fdHolderBufferSize)); //设置接收缓冲区
    setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));//允许SCM_CREDENTIALS 控制消息的接收

    if (access(INIT_HOLDER_SOCKET_PATH, F_OK) == 0) { //#define INIT_HOLDER_SOCKET_PATH "/dev/unix/socket/fd_holder"
        INIT_LOGI("%s exist, remove it", INIT_HOLDER_SOCKET_PATH);
        unlink(INIT_HOLDER_SOCKET_PATH);
    }
    struct sockaddr_un addr;
    addr.sun_family = AF_UNIX;
    if (strncpy_s(addr.sun_path, sizeof(addr.sun_path),
        INIT_HOLDER_SOCKET_PATH, strlen(INIT_HOLDER_SOCKET_PATH)) != 0) {
        INIT_LOGE("Faild to copy fd hoder socket path");
        close(sock);
        return -1;
    }
    socklen_t len = (socklen_t)(offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path) + 1);
    if (bind(sock, (struct sockaddr *)&addr, len) < 0) {
        INIT_LOGE("Failed to binder fd folder socket %d", errno);
        close(sock);
        return -1;
    }

    // Owned by root
    if (lchown(addr.sun_path, 0, 0)) {
        INIT_LOGW("Failed to change owner of fd holder socket, err = %d", errno);
    }
    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
    if (fchmodat(AT_FDCWD, addr.sun_path, mode, AT_SYMLINK_NOFOLLOW)) {
        INIT_LOGW("Failed to change mode of fd holder socket, err = %d", errno);
    }
    INIT_LOGI("Init fd holder socket done");
    return sock;
}

base\startup\init\services\init\standard\init_control_fd_service.c

void InitControlFd(void)
{
    //初始化/dev/unix/socket/init_control_fd,对应的处理函数ProcessControlFd
    CmdServiceInit(INIT_CONTROL_FD_SOCKET_PATH, ProcessControlFd, LE_GetDefaultLoop());
    return;
}

base\startup\init\services\init\adapter\init_adapter.c

由于只有小型系统定义了NEED_EXEC_RCS_LINUX,所以标准系统不会执行
init程序首先会调用/etc/init.d/rcS脚本,rcS脚本执行第一条命令为"/bin/mount -a”,该命令会加载fstab文件,在fstab中的命令执行完后rcS将顺序调用Sxxx脚本完成设备节点创建和扫描、文件权限配置等操作。
void SystemExecuteRcs(void)
{
#if (defined __LINUX__) && (defined NEED_EXEC_RCS_LINUX)
    pid_t retPid = fork();
    if (retPid < 0) {
        INIT_LOGE("ExecuteRcs, fork failed! err %d.", errno);
        return;
    }

    // child process
    if (retPid == 0) {
        INIT_LOGI("ExecuteRcs, child process id %d.", getpid());
        if (execle("/bin/sh", "sh", "/etc/init.d/rcS", NULL, NULL) != 0) {
            INIT_LOGE("ExecuteRcs, execle failed! err %d.", errno);
        }
        _exit(0x7f); // 0x7f: user specified
    }

    // init process
    sem_t sem;
    if (sem_init(&sem, 0, 0) != 0) {
        INIT_LOGE("ExecuteRcs, sem_init failed, err %d.", errno);
        return;
    }
    SignalRegWaitSem(retPid, &sem);

    // wait until rcs process exited
    if (sem_wait(&sem) != 0) {
        INIT_LOGE("ExecuteRcs, sem_wait failed, err %d.", errno);
    }
#endif

base\startup\init\services\init\standard\init.c
SystemConfig

void SystemConfig(const char *uptime)
{
    INIT_TIMING_STAT timingStat;
    //设置/proc/self/oom_score_adj 值为-1000
    InitSysAdj();
    HOOK_EXEC_OPTIONS options;

    options.flags = 0;
    options.preHook = InitPreHook;
    options.postHook = InitPostHook;
    //主要就是给g_initWorkspace结构体赋值
    InitServiceSpace();
    HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, (void *)&timingStat, (void *)&options);
    //记录开机事件init.prepare
    RecordInitBootEvent("init.prepare");

    HookMgrExecute(GetBootStageHookMgr(), INIT_PRE_PARAM_SERVICE, (void *)&timingStat, (void *)&options);
    if (InitParamService() != 0) {
        ExecReboot("panic");
    }
    //将解析的cfg值放入对应的groupNodes中
    InitParseGroupCfg();
    //记录开机事件RecordInitBootEvent
    //设置开机的时间属性ohos.boot.time.init
    RegisterBootStateChange(BootStateChange);

    INIT_LOGI("boot stage: init finish.");
    // load SELinux context and policy
    // Do not move position!
    //加载selinux上下文和策略
    PluginExecCmdByName("loadSelinuxPolicy", "");
    RecordInitBootEvent("init.prepare");

    // after selinux loaded
    /*init是一个守护进程,为了防止init的子进程成为僵尸进程(zombie process),需要init在子进程在结束时获取子进程的结束码,通过结束码将程序表中的子进程移除,防止成为僵尸进程的子进程占用程序表的空间(程序表的空间达到上限时,系统就不能再启动新的进程了,会引起严重的系统问题)
    在linux当中,父进程是通过捕捉SIGCHLD信号来得知子进程运行结束的情况,SIGCHLD信号会在子进程终止的时候发出*/
    SignalInit();

    RecordInitBootEvent("init.ParseCfg");
    //加载系统的一些特殊参数
    LoadSpecialParam();

    // parse parameters
    HookMgrExecute(GetBootStageHookMgr(), INIT_PRE_PARAM_LOAD, (void *)&timingStat, (void *)&options);
    //加载系统的参数
    InitLoadParamFiles();

    // Write kernel uptime into system parameter
    //设置kernel启动时间
    WriteUptimeSysParam("ohos.boot.time.kernel", uptime);

    // read config
    HookMgrExecute(GetBootStageHookMgr(), INIT_PRE_CFG_LOAD, (void *)&timingStat, (void *)&options);
    //读取cfg参数
    ReadConfig();
    RecordInitBootEvent("init.ParseCfg");
    INIT_LOGI("boot stage: parse config file finish.");
    HookMgrExecute(GetBootStageHookMgr(), INIT_POST_CFG_LOAD, (void *)&timingStat, (void *)&options);

    //根据属性const.sandbox判断sandbox是否启用
    IsEnableSandbox();
    // execute init
    //触发执行对应的init*.cfg中job service
    PostTrigger(EVENT_TRIGGER_BOOT, "pre-init", strlen("pre-init"));
    PostTrigger(EVENT_TRIGGER_BOOT, "init", strlen("init"));
    TriggerServices(START_MODE_BOOT);
    PostTrigger(EVENT_TRIGGER_BOOT, "post-init", strlen("post-init"));
    TriggerServices(START_MODE_NORMAL);
    clock_gettime(CLOCK_MONOTONIC, &(g_bootJob.startTime));
}
.
.
.
static void InitLoadParamFiles(void)
{
    if (InUpdaterMode() != 0) {
        LoadDefaultParams("/etc/param/ohos_const", LOAD_PARAM_NORMAL);
        LoadDefaultParams("/etc/param", LOAD_PARAM_ONLY_ADD);
        LoadDefaultParams("/vendor/etc/param", LOAD_PARAM_ONLY_ADD);
        return;
    }

    // Load developer mode param
    LoadDefaultParams("/proc/dsmm/developer", LOAD_PARAM_NORMAL);

    // Load const params, these can't be override!
    LoadDefaultParams("/system/etc/param/ohos_const", LOAD_PARAM_NORMAL);
    CfgFiles *files = GetCfgFiles("etc/param");
    for (int i = MAX_CFG_POLICY_DIRS_CNT - 1; files && i >= 0; i--) {
        if (files->paths[i]) {
            LoadDefaultParams(files->paths[i], LOAD_PARAM_ONLY_ADD);
        }
    }
    FreeCfgFiles(files);
}

cfg文件 (具体见:cfg文件解析.md)
base\startup\init\services\init\init_group_manager.c

void InitServiceSpace(void)
{
    if (g_initWorkspace.initFlags != 0) {
        return;
    }
    HashInfo info = {
        GroupNodeNodeCompare,
        GroupNodeKeyCompare,
        GroupNodeGetNodeHashCode,
        GroupNodeGetKeyHashCode,
        GroupNodeFree,
        GROUP_HASHMAP_BUCKET
    };
    for (size_t i = 0; i < ARRAY_LENGTH(g_initWorkspace.hashMap); i++) {
        int ret = OH_HashMapCreate(&g_initWorkspace.hashMap[i], &info);
        if (ret != 0) {
            INIT_LOGE("%s", "Failed to create hash map");
        }
    }

    for (int i = 0; i < NODE_TYPE_MAX; i++) {
        g_initWorkspace.groupNodes[i] = NULL;
    }
    // get boot mode, set default mode
    strcpy_s(g_initWorkspace.groupModeStr, sizeof(g_initWorkspace.groupModeStr), BOOT_GROUP_DEFAULT);
    int ret = GetParameterFromCmdLine(BOOT_GROUP_NAME,
        g_initWorkspace.groupModeStr, sizeof(g_initWorkspace.groupModeStr));
    if (ret != 0) {
        INIT_LOGV("Failed to get boot group");
        if (GetBootModeFromMisc() == GROUP_CHARGE) {
            strcpy_s(g_initWorkspace.groupModeStr, sizeof(g_initWorkspace.groupModeStr), "device.charge.group");
        }
    }
    INIT_LOGI("boot start %s", g_initWorkspace.groupModeStr);
    //device.boot.group 系统默认配置,触发执行配置文件中的所有的job和服务。
    //device.charge.group charge模式,限制只启动改文件中允许的job和服务。
    g_initWorkspace.groupMode = GetBootGroupMode();
    g_initWorkspace.initFlags = 1;
}
.
.
.
int InitParseGroupCfg(void)
{
    char buffer[128] = {0}; // 128 buffer size
    //  /data/init_ut/system/etc
    char *realPath = GetAbsolutePath(GROUP_DEFAULT_PATH,
        g_initWorkspace.groupModeStr, buffer, sizeof(buffer));
    INIT_ERROR_CHECK(realPath != NULL, return -1,
        "Failed to get path for %s", g_initWorkspace.groupModeStr);
    InitParseGroupCfg_(realPath);
    InitGroupNode *groupRoot = g_initWorkspace.groupNodes[NODE_TYPE_GROUPS];
    int level = 0;
    while ((groupRoot != NULL) && (level < GROUP_IMPORT_MAX_LEVEL)) { // for more import
        g_initWorkspace.groupNodes[NODE_TYPE_GROUPS] = NULL;
        InitImportGroupCfg_(groupRoot);
        groupRoot = g_initWorkspace.groupNodes[NODE_TYPE_GROUPS];
        level++;
    }
    InitFreeGroupNodes_(g_initWorkspace.groupNodes[NODE_TYPE_GROUPS]);
    g_initWorkspace.groupNodes[NODE_TYPE_GROUPS] = NULL;
    return 0;
}

LoadSpecialParam
base\startup\init\services\param\linux\param_service.c

void LoadSpecialParam(void)
{
    // read param area size from cfg and save to dac
    LoadParamAreaSize();
    // read selinux label
    LoadSelinuxLabel("init");
    // from cmdline
    LoadParamFromCmdLine();
    // from build
    LoadParamFromBuild();
}

base\startup\init\services\param\manager\param_server.c

INIT_LOCAL_API void LoadParamAreaSize(void)
{
    LoadDefaultParam_("/sys_prod/etc/param/ohos.para.size", 0, NULL, 0, LoadOneParamAreaSize_);
    LoadDefaultParam_(PARAM_AREA_SIZE_CFG, 0, NULL, 0, LoadOneParamAreaSize_);
}
.
.
.
INIT_LOCAL_API void LoadParamFromBuild(void)
{
    PARAM_LOGI("load parameters from build ");
#ifdef INCREMENTAL_VERSION
    if (strlen(INCREMENTAL_VERSION) > 0) {
        WriteParam("const.product.incremental.version", INCREMENTAL_VERSION, NULL, LOAD_PARAM_NORMAL);
    }
#endif
#ifdef BUILD_TYPE
    if (strlen(BUILD_TYPE) > 0) {
        WriteParam("const.product.build.type", BUILD_TYPE, NULL, LOAD_PARAM_NORMAL);
    }
#endif
#ifdef BUILD_USER
    if (strlen(BUILD_USER) > 0) {
        WriteParam("const.product.build.user", BUILD_USER, NULL, LOAD_PARAM_NORMAL);
    }
#endif
#ifdef BUILD_TIME
    if (strlen(BUILD_TIME) > 0) {
        WriteParam("const.product.build.date", BUILD_TIME, NULL, LOAD_PARAM_NORMAL);
    }
#endif
#ifdef BUILD_HOST
    if (strlen(BUILD_HOST) > 0) {
        WriteParam("const.product.build.host", BUILD_HOST, NULL, LOAD_PARAM_NORMAL);
    }
#endif
#ifdef BUILD_ROOTHASH
    if (strlen(BUILD_ROOTHASH) > 0) {
        WriteParam("const.ohos.buildroothash", BUILD_ROOTHASH, NULL, LOAD_PARAM_NORMAL);
    }
#endif
}

ReadConfig
base\startup\init\services\init\init_config.c

void ReadConfig(void)
{
    // parse cfg
    char buffer[32] = {0}; // 32 reason max leb
    uint32_t len = sizeof(buffer);
    //读取启动模式,根据不同模式解析对应的cfg文件
    SystemReadParam("ohos.boot.mode", buffer, &len);
    INIT_LOGI("ohos.boot.mode %s", buffer);
    if (strcmp(buffer, "charger_mode") == 0) {
        ParseInitCfg(INIT_CONFIGURATION_FILE, NULL);
        ReadFileInDir(OTHER_CHARGE_PATH, ".cfg", ParseInitCfg, NULL);
        ParseInitCfgByPriority();
    } else if (strcmp(buffer, "charger") == 0) {
        ParseInitCfg(INIT_CONFIGURATION_FILE, NULL);
        ReadFileInDir(OTHER_CHARGE_PATH, ".cfg", ParseInitCfg, NULL);
    } else if (InUpdaterMode() == 0) {
        ParseInitCfg(INIT_CONFIGURATION_FILE, NULL);
        ParseInitCfgByPriority();
    } else {
        ReadFileInDir("/etc", ".cfg", ParseInitCfg, NULL);
    }
}
static void ParseInitCfgContents(const char *cfgName, const cJSON *root)
{
    INIT_ERROR_CHECK(root != NULL, return, "Root is null");
    ConfigContext context = { INIT_CONTEXT_MAIN };
    context.type = GetConfigContextType(cfgName);
    INIT_LOGV("Parse %s configs in context %d", cfgName, context.type);
    // 解析cfg文件中的services
    ParseAllServices(root, &context);
    // 解析cfg文件中的jobs
    ParseAllJobs(root, &context);
    // parse imports
    //解析所有导入cfg文件
    ParseAllImports(root);
}

int ParseInitCfg(const char *configFile, void *context)
{
    UNUSED(context);
    INIT_LOGV("Parse init configs from %s", configFile);
    char *fileBuf = ReadFileToBuf(configFile);
    INIT_ERROR_CHECK(fileBuf != NULL, return -1, "Cfg error, %s not found", configFile);

    cJSON *fileRoot = cJSON_Parse(fileBuf);
    INIT_ERROR_CHECK(fileRoot != NULL, free(fileBuf);
        return -1, "Cfg error, failed to parse json %s ", configFile);

    ParseInitCfgContents(configFile, fileRoot);
    cJSON_Delete(fileRoot);
    free(fileBuf);
    return 0;
}

SystemRun
base\startup\init\services\init\standard\init.c

void SystemRun(void)
{
    StartParamService();
}

base\startup\init\services\param\linux\param_service.c

int StartParamService(void)
{
    // read selinux label
    LoadSelinuxLabel("permission");
    return ParamServiceStart();
}

base\startup\init\services\param\linux\param_msgadp.c

int ParamServiceStart(void)
{
    LE_RunLoop(LE_GetDefaultLoop());
    return 0;
}

samgr系统服务进程

samgr是各个SystemAbility的服务进程中心,每个SA的启动都需要向samgr注册,然后分配到一个ID,通过ID才能访问到该SA。
samgr由init进程启动,由之前的SystemConfig函数可知,执行post-init的时候会触发early-fs,此时执行samgr的job。samgr服务配置的模式为boot则会在init阶段启动

void SystemConfig(const char *uptime)
{
    .....
    // execute init
    PostTrigger(EVENT_TRIGGER_BOOT, "pre-init", strlen("pre-init"));
    PostTrigger(EVENT_TRIGGER_BOOT, "init", strlen("init"));
    TriggerServices(START_MODE_BOOT);
    PostTrigger(EVENT_TRIGGER_BOOT, "post-init", strlen("post-init"));
    TriggerServices(START_MODE_NORMAL);
    clock_gettime(CLOCK_MONOTONIC, &(g_bootJob.startTime));
}

base\startup\init\services\etc\init.cfg

{
    "name" : "post-init",
    "cmds" : [
        "trigger early-fs",
        "trigger fs",
        "trigger post-fs",
        "trigger late-fs",
        "trigger post-fs-data",
        "trigger firmware_mounts_complete",
        "trigger early-boot",
        "trigger boot"
    ]
}

samgr的cfg文件如下。(服务介绍详见:服务管理.md
foundation\systemabilitymgr\samgr\etc\samgr_standard.cfg

{
    "jobs" : [{
            "name" : "early-fs",
            "cmds" : [
                "mkdir /data/samgr 0740 samgr samgr"
            ]
        }
    ],
    "services" : [{
            "name" : "samgr",
            "path" : ["/system/bin/samgr"],
            "critical" : [1, 1, 60],
            "uid" : "samgr",
            "gid" : ["samgr", "readproc"],
            "bootevents":"bootevent.samgr.ready",
            "permission": [
                "ohos.permission.DISTRIBUTED_DATASYNC",
                "ohos.permission.ACCESS_SERVICE_DM",
                "ohos.permission.RECEIVER_STARTUP_COMPLETED",
                "ohos.permission.MANAGE_LOCAL_ACCOUNTS",
                "ohos.permission.INTERACT_ACROSS_LOCAL_ACCOUNTS",
                "ohos.permission.LOCATION",
                "ohos.permission.GET_WIFI_INFO",
                "ohos.permission.USE_BLUETOOTH",
                "ohos.permission.DISCOVER_BLUETOOTH",
                "ohos.permission.MANAGE_SECURE_SETTINGS",
                "ohos.permission.LISTEN_BUNDLE_CHANGE",
                "ohos.permission.STORAGE_MANAGER",
                "ohos.permission.RECEIVE_SMS",
                "ohos.permission.GET_TELEPHONY_STATE",
		"ohos.permission.PUBLISH_SYSTEM_COMMON_EVENT"
            ],
            "secon" : "u:r:samgr:s0",
            "start-mode" : "boot" //启动模式
        }
    ]
}

foundation进程

ams,wms等服务都在foundation进程中。
foundation是一个特殊的SA服务进程,提供用户程序管理框架及基础服务,该进程负责应用的生命周期管理,ready可进行startAbility/connectAbility。当多个服务都完成对应的启动事件后,由bootevents投票,在init进程中设置bootevent.boot.completed事件为true,表示系统启动完成。
在foundation监控到此事件再以CES事件的方式广播出去,让应用能够检测到。foundation服务进程想应用孵化器appspawn发送应用启动请求。appspawn接收到应用启动请求,直接孵化出应用进程。当foundation启动Openharmony应用Home即我们看到的桌面程序,至此从开机到应用启动所有过程就完成了。
foundation在post-init阶段启动
foundation\systemabilitymgr\safwk\etc\profile\foundation.cfg

"services" : [{
            "name" : "foundation",
            "path" : ["/system/bin/sa_main", "/system/profile/foundation.json"],
            "critical" : [1, 4, 240],
            "importance" : -20,
            "uid" : "foundation",
            "permission" : [
                "ohos.permission.INPUT_MONITORING",
                "ohos.permission.PERMISSION_USED_STATS",
                "ohos.permission.DISTRIBUTED_SOFTBUS_CENTER",
                "ohos.permission.DISTRIBUTED_DATASYNC",
                "ohos.permission.MANAGE_AUDIO_CONFIG",
                "ohos.permission.WRITE_CALL_LOG",
                "ohos.permission.READ_CONTACTS",
                "ohos.permission.READ_DFX_SYSEVENT",
                "ohos.permission.GRANT_SENSITIVE_PERMISSIONS",
                "ohos.permission.REVOKE_SENSITIVE_PERMISSIONS",
                "ohos.permission.MANAGE_SECURE_SETTINGS",
                "ohos.permission.START_ABILITIES_FROM_BACKGROUND",
                "ohos.permission.ACCESS_SERVICE_DM",
                "ohos.permission.STORAGE_MANAGER",
                "ohos.permission.PROXY_AUTHORIZATION_URI",
                "ohos.permission.ABILITY_BACKGROUND_COMMUNICATION",
                "ohos.permission.USE_USER_IDM",
                "ohos.permission.MANAGE_LOCAL_ACCOUNTS",
                "ohos.permission.LISTEN_BUNDLE_CHANGE",
                "ohos.permission.GET_TELEPHONY_STATE",
                "ohos.permission.SEND_MESSAGES",
                "ohos.permission.CONNECT_CELLULAR_CALL_SERVICE",
                "ohos.permission.SET_TELEPHONY_STATE",
                "ohos.permission.VIBRATE",
                "ohos.permission.SYSTEM_LIGHT_CONTROL",
                "ohos.permission.MANAGE_HAP_TOKENID",
                "ohos.permission.WRITE_WHOLE_CALENDAR",
                "ohos.permission.UPDATE_CONFIGURATION",
                "ohos.permission.REPORT_RESOURCE_SCHEDULE_EVENT",
                "ohos.permission.START_INVISIBLE_ABILITY",
                "ohos.permission.GET_BUNDLE_INFO",
                "ohos.permission.GET_SUSPEND_STATE",
                "ohos.permission.PUBLISH_SYSTEM_COMMON_EVENT",
                "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED",
                "ohos.permission.GET_SENSITIVE_PERMISSIONS",
                "ohos.permission.CLEAN_APPLICATION_DATA",
                "ohos.permission.REMOVE_CACHE_FILES",
                "ohos.permission.INSTALL_SANDBOX_BUNDLE",
                "ohos.permission.USE_BLUETOOTH",
                "ohos.permission.CONNECTIVITY_INTERNAL",
                "ohos.permission.GET_RUNNING_INFO",
                "ohos.permission.INTERACT_ACROSS_LOCAL_ACCOUNTS",
                "ohos.permission.ACCESS_BLUETOOTH",
                "ohos.permission.RUNNING_STATE_OBSERVER"
            ],
            "permission_acls":[
                "ohos.permission.MANAGE_HAP_TOKENID",
                "ohos.permission.GRANT_SENSITIVE_PERMISSIONS",
                "ohos.permission.INPUT_MONITORING",
                "ohos.permission.REVOKE_SENSITIVE_PERMISSIONS",
                "ohos.permission.START_INVISIBLE_ABILITY",
                "ohos.permission.INSTALL_SANDBOX_BUNDLE"
            ],
            "gid" : ["system", "appspawn", "update"],
            "caps" : ["SYS_PTRACE", "KILL"],
            "bootevents": [
                "bootevent.wms.fullscreen.ready",
                "bootevent.appfwk.ready",
                "bootevent.lockscreen.ready"
            ],
            "jobs" : {
                "on-start" : "services:foundation",
                "on-restart" : "services:restartfoundation"
            },
            "secon" : "u:r:foundation:s0"
        }
    ]

系统服务框架组件(SystemAbility)(具体详见: 系统服务框架部件.md)

SystemAbility实现一般采用XXX.cfg + profile.json + libXXX.z.so的方式由init进程执行对应的XXX.cfg文件拉起相关SystemAbility进程。

AbilityManagerService的启动

系统服务框架部件.md可知的服务配置需要对应.json文件和BUILD.gn文件以及cfg文件。
对应的ams的json和BUILD.gn文件如下:
foundation\ability\ability_runtime\services\sa_profile\180.json
foundation\ability\ability_runtime\services\sa_profile\BUILD.gn

{
    "process": "foundation",
    "systemability": [
        {
            "name": 180,
            "libpath": "libabilityms.z.so",
            "run-on-create": true,
            "distributed": false,
            "dump_level": 1
        }
    ]
}

import("//build/ohos/sa_profile/sa_profile.gni")

ohos_sa_profile("ams_sa_profile") {
  sources = [
    "180.json",
    "182.json",
    "183.json",
    "184.json",
    "501.json",
  ]

  part_name = "ability_runtime"
}

由于ams跑在foundation进程中,所以对应的文件查看foundation.cfg
所以查看对应的/system/bin/sa_main的流程,找到对应的main函数
foundation\systemabilitymgr\safwk\services\safwk\src\main.cpp

int main(int argc, char *argv[])
{
    HILOGD(TAG, "[PerformanceTest] SAFWK main entry process starting!");
    // find update list
    //检测服务cfg文件中是否配置按需启动ondemand
    bool checkOnDemand = true;
    string updateList;
    for (int i = 0; i < argc - 1; ++i) {
        if (PARAM_PREFIX_U.compare(argv[i]) == 0) {
            if (i == EVENT_INDEX) {
                checkOnDemand = false;
            }
            updateList = argv[i + 1];
            break;
        }
    }

    if (!updateList.empty()) {
        LocalAbilityManager::GetInstance().SetUpdateList(updateList);
    }

    // Load ondemand system abilities related shared libraries from specific json-format profile
    // when this process starts.
    //从.json配置文件加载与ondemand系统功能相关的共享库(如:ams配置的180.json中加载libabilityms.z.so )
    int32_t saId = DEFAULT_SAID;
    if (checkOnDemand && argc > ONDEMAND_LOAD) {
        nlohmann::json eventMap;
        saId = ParseArgv(argv, eventMap);
        if (!CheckSaId(saId)) {
            HILOGE(TAG, "saId is invalid!");
            return 0;
        }
        LocalAbilityManager::GetInstance().SetStartReason(saId, eventMap);
    }
    
    //启动服务进程
    DoStartSAProcess(argc, argv, saId);
    return 0;
}

....

static int DoStartSAProcess(int argc, char *argv[], int32_t saId)
{
    auto setProcessName = [argc, argv](const string& name) -> void {
        char *endCh = strchr(argv[argc - 1], 0);
        if (endCh == nullptr) {
            HILOGW(TAG, "argv is invalid");
            return;
        }
        uintptr_t start = reinterpret_cast<uintptr_t>(argv[0]);
        uintptr_t end = reinterpret_cast<uintptr_t>(endCh);
        uintptr_t argvSize = end - start;

        if (memset_s(argv[0], argvSize, 0, argvSize) != EOK) {
            HILOGW(TAG, "failed to clear argv:%{public}s", strerror(errno));
            return;
        }
        if (strcpy_s(argv[0], argvSize, name.c_str()) != EOK) {
            HILOGW(TAG, "failed to set process name:%{public}s", strerror(errno));
            return;
        }
        HILOGI(TAG, "Set process name to %{public}s", argv[0]);
    };
    // Load default system abilities related shared libraries from specific format profile
    // when this process starts.
    string profilePath(DEFAULT_JSON);
    if (argc > DEFAULT_LOAD) {
        string filePath(argv[PROFILE_INDEX]);
        //寻找对应的json文件
        if (filePath.empty() || filePath.find(".json") == string::npos) {
            HILOGE(TAG, "profile file path is invalid!");
            return 0;
        }
        SetProcName(filePath, setProcessName);
        profilePath = std::move(filePath);
    }
    LocalAbilityManager::GetInstance().DoStartSAProcess(profilePath, saId);
    return 0;
}

foundation\systemabilitymgr\safwk\services\safwk\src\local_ability_manager.cpp

void LocalAbilityManager::DoStartSAProcess(const std::string& profilePath, int32_t saId)
{
    startBegin_ = GetTickCount();
    HILOGD(TAG, "SA:%{public}d", saId);
    string realProfilePath = "";
    //检测文件路径是否正确
    if (!CheckAndGetProfilePath(profilePath, realProfilePath)) {
        HILOGE(TAG, "DoStartSAProcess invalid path");
        return;
    }
    {
        std::string traceTag = GetTraceTag(realProfilePath);
        HITRACE_METER_NAME(HITRACE_TAG_SAMGR, traceTag);
        //初始化sa profiles
        bool ret = InitSystemAbilityProfiles(realProfilePath, saId);
        if (!ret) {
            HILOGE(TAG, "InitSystemAbilityProfiles no right profile, will exit");
            return;
        }
        //等待samg的启动
        ret = CheckSystemAbilityManagerReady();
        if (!ret) {
            HILOGE(TAG, "CheckSystemAbilityManagerReady failed! will exit");
            return;
        }
        //启动SA
        ret = Run(saId);
        if (!ret) {
            HILOGE(TAG, "Run failed! will exit");
            return;
        }
    }

    IPCSkeleton::JoinWorkThread();
    ClearResource();
    HILOGE(TAG, "JoinWorkThread stop, will exit");
}

.....

bool LocalAbilityManager::CheckAndGetProfilePath(const std::string& profilePath, std::string& realProfilePath)
{
    if (profilePath.length() > PATH_MAX) {
        HILOGE(TAG, "profilePath length too long!");
        return false;
    }
    char realPath[PATH_MAX] = {'\0'};
    if (realpath(profilePath.c_str(), realPath) == nullptr) {
        HILOGE(TAG, "file path does not exist!");
        return false;
    }
    // realProfilePath must begin with "/system/profile/" or begin with "/system/usr/"
    realProfilePath = realPath;
    if (realProfilePath.find(PROFILES_DIR) != 0 && realProfilePath.find(DEFAULT_DIR) != 0) {
        HILOGE(TAG, "file path is not matched");
        return false;
    }
    return true;
}

.....

bool LocalAbilityManager::InitSystemAbilityProfiles(const std::string& profilePath, int32_t saId)
{
    HILOGD(TAG, "[PerformanceTest]parse sa profiles!");
    int64_t begin = GetTickCount();
    //解析profile
    bool ret = profileParser_->ParseSaProfiles(profilePath);
    if (!ret) {
        HILOGW(TAG, "ParseSaProfiles failed!");
        return false;
    }

    procName_ = profileParser_->GetProcessName();
    auto saInfos = profileParser_->GetAllSaProfiles();
    std::string process = Str16ToStr8(procName_);
    HILOGI(TAG, "[PerformanceTest]parse process:%{public}s profiles finished, spend:%{public}"
        PRId64 " ms", process.c_str(), (GetTickCount() - begin));
    std::string path = PREFIX + process + SUFFIX;
    bool isExist = profileParser_->CheckPathExist(path);
    if (isExist) {
        CheckTrustSa(path, process, saInfos);
    }
    return InitializeSaProfiles(saId);
}

bool LocalAbilityManager::InitializeSaProfiles(int32_t saId)
{
    if (saId != DEFAULT_SAID) {
        return InitializeOnDemandSaProfile(saId);
    } else {
        return InitializeRunOnCreateSaProfiles(BOOT_START);
    }
}

void LocalAbilityManager::CheckTrustSa(const std::string& path, const std::string& process,
    const std::list<SaProfile>& saInfos)
{
    HILOGD(TAG, "CheckTrustSa start");
    std::map<std::u16string, std::set<int32_t>> trustMaps;
    //解析trust sa profiles,并移除不受信任的sa
    //foundation进程受信任profile配置在如下文件中:
    //foundation\systemabilitymgr\safwk\etc\profile\foundation_trust.json
    bool ret = profileParser_->ParseTrustConfig(path, trustMaps);
    if (ret && !trustMaps.empty()) {
        // 1.get allowed sa set in the process
        const auto& saSets = trustMaps[Str8ToStr16(process)];
        // 2.check to-load sa in the allowed sa set, and if to-load sa not in the allowed, will remove and not load it
        for (const auto& saInfo : saInfos) {
            if (saSets.find(saInfo.saId) == saSets.end()) {
                HILOGW(TAG, "SA:%{public}d not allow to load in %{public}s", saInfo.saId, process.c_str());
                profileParser_->RemoveSaProfile(saInfo.saId);
            }
        }
    }
}

.....

bool LocalAbilityManager::CheckSystemAbilityManagerReady()
{
    int32_t timeout = RETRY_TIMES_FOR_SAMGR;
    constexpr int32_t duration = std::chrono::microseconds(MILLISECONDS_WAITING_SAMGR_ONE_TIME).count();
    sptr<ISystemAbilityManager> samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
    //循环检测samg是否初始化完成
    while (samgrProxy == nullptr) {
        HILOGI(TAG, "%{public}s waiting for samgr...", Str16ToStr8(procName_).c_str());
        if (timeout > 0) {
            usleep(duration);
            samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
        } else {
            HILOGE(TAG, "wait for samgr time out (10s)");
            return false;
        }
        timeout--;
    }
    return true;
}

.....

bool LocalAbilityManager::InitializeRunOnCreateSaProfiles(uint32_t bootPhase)
{
    /*bootphase:可不设置;可以设置的值有三种:BootStartPhase、CoreStartPhase、OtherStartPhase(默认类型),三种优先级依次降低,当同一个进程中,会优先拉起注册配置BootStartPhase的SystemAbility,然后是配置了CoreStartPhase的SystemAbility,最后是OtherStartPhase;当高优先级的SystemAbility全部启动注册完毕才会启动下一级的SystemAbility的注册启动。*/
    if (bootPhase > OTHER_START) {
        return false;
    }
    int64_t begin = GetTickCount();
    HILOGD(TAG, "[PerformanceTest]load phase %{public}d libraries", bootPhase);
    //dlopen各sa所在的so库
    profileParser_->OpenSo(bootPhase);
    HILOGI(TAG, "[PerformanceTest]load process:%{public}s phase %{public}d finished, spend:%{public}" PRId64 " ms",
        Str16ToStr8(procName_).c_str(), bootPhase, (GetTickCount() - begin));
    auto& saProfileList = profileParser_->GetAllSaProfiles();
    if (saProfileList.empty()) {
        HILOGW(TAG, "sa profile is empty");
        return false;
    }
    for (const auto& saProfile : saProfileList) {
        if (saProfile.bootPhase != bootPhase) {
            continue;
        }
        //将sa对象注册到abilityPhaseMap_中
        if (!InitializeSaProfilesInnerLocked(saProfile)) {
            HILOGW(TAG, "SA:%{public}d init fail", saProfile.saId);
            continue;
        }
    }
    return true;
}

bool LocalAbilityManager::InitializeSaProfilesInnerLocked(const SaProfile& saProfile)
{
    std::unique_lock<std::shared_mutex> readLock(abilityMapLock_);
    auto iterProfile = abilityMap_.find(saProfile.saId);
    if (iterProfile == abilityMap_.end()) {
        HILOGW(TAG, "SA:%{public}d not found", saProfile.saId);
        return false;
    }
    auto systemAbility = iterProfile->second;
    if (systemAbility == nullptr) {
        HILOGW(TAG, "SA:%{public}d is null", saProfile.saId);
        return false;
    }
    auto& saList = abilityPhaseMap_[saProfile.bootPhase];
    saList.emplace_back(systemAbility);
    return true;
}

......

bool LocalAbilityManager::Run(int32_t saId)
{
    HILOGD(TAG, "local ability manager is running...");
    bool addResult = AddLocalAbilityManager();
    if (!addResult) {
        HILOGE(TAG, "failed to add local abilitymanager");
        return false;
    }
    HILOGD(TAG, "success to add process name:%{public}s", Str16ToStr8(procName_).c_str());
    //获取系统支持的并发线程数
    uint32_t concurrentThreads = std::thread::hardware_concurrency();
    HILOGI(TAG, "concurrentThreads is %{public}d, process:%{public}s, SA:%{public}d",
        concurrentThreads, Str16ToStr8(procName_).c_str(), saId);
    //通过线程池启动线程,可以通过增加线程数优化sa启动时间
    initPool_->Start(concurrentThreads);
    initPool_->SetMaxTaskNum(MAX_TASK_NUMBER);

    //对应ondemand类型的sa的信息添加到samgr
    RegisterOnDemandSystemAbility(saId);
    //遍历sa,调用对应sa的start()函数
    FindAndStartPhaseTasks(saId);
    initPool_->Stop();
    return true;
}

bool LocalAbilityManager::AddLocalAbilityManager()
{
    auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
    if (samgrProxy == nullptr) {
        HILOGE(TAG, "failed to get samgrProxy");
        return false;
    }

    if (localAbilityManager_ == nullptr) {
        localAbilityManager_ = this;
    }
    //通过 IPC 调用 samgr 服务的 AddSystemProcess()方法将服务进程(本质上是一个绑定了服务相关信息的 lsamgr 实例)注册到 samgr,然后启动服务进程
    int32_t ret = samgrProxy->AddSystemProcess(procName_, localAbilityManager_);
    return ret == ERR_OK;
}

......

void LocalAbilityManager::RegisterOnDemandSystemAbility(int32_t saId)
{
    auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
    if (samgrProxy == nullptr) {
        HILOGI(TAG, "failed to get samgrProxy");
        return;
    }

    auto& saProfileList = profileParser_->GetAllSaProfiles();
    for (const auto& saProfile : saProfileList) {
        if (NeedRegisterOnDemand(saProfile, saId)) {
            HILOGD(TAG, "register ondemand SA:%{public}d to samgr", saProfile.saId);
            //SA 对应的系统进程启动之后,便需要加载启动 SA 自身。首先,samgr 调用 AddOnDemandSystemAbilityInfo(),将对应的 SA 实例与服务进程进行绑定,并准备启动对应的 SA
            //将对应ondemand类型的sa的信息添加到samgr
            int32_t ret = samgrProxy->AddOnDemandSystemAbilityInfo(saProfile.saId, procName_);
            if (ret != ERR_OK) {
                HILOGI(TAG, "failed to add ability info for on-demand SA:%{public}d", saProfile.saId);
            }
        }
    }
}

.....

void LocalAbilityManager::FindAndStartPhaseTasks(int32_t saId)
{
    if (saId == DEFAULT_SAID) {
        for (uint32_t bootPhase = BOOT_START; bootPhase <= OTHER_START; ++bootPhase) {
            auto iter = abilityPhaseMap_.find(bootPhase);
            if (iter != abilityPhaseMap_.end()) {
                StartPhaseTasks(iter->second);
                InitializeRunOnCreateSaProfiles(bootPhase + 1);
                WaitForTasks();
            } else {
                InitializeRunOnCreateSaProfiles(bootPhase + 1);
            }
        }
    } else {
        for (uint32_t bootPhase = BOOT_START; bootPhase <= OTHER_START; ++bootPhase) {
            auto iter = abilityPhaseMap_.find(bootPhase);
            if (iter != abilityPhaseMap_.end()) {
                StartPhaseTasks(iter->second);
                WaitForTasks();
            }
        }
    }
}

//启动sa
void LocalAbilityManager::StartPhaseTasks(const std::list<SystemAbility*>& systemAbilityList)
{
    if (systemAbilityList.empty()) {
        return;
    }

    for (auto systemAbility : systemAbilityList) {
        if (systemAbility != nullptr) {
            HILOGD(TAG, "add phase task for SA:%{public}d", systemAbility->GetSystemAbilitId());
            std::lock_guard<std::mutex> autoLock(startPhaseLock_);
            ++startTaskNum_;
            auto task = std::bind(&LocalAbilityManager::StartSystemAbilityTask, this, systemAbility);
            initPool_->AddTask(task);
        }
    }
}

void LocalAbilityManager::StartSystemAbilityTask(SystemAbility* ability)
{
    if (ability != nullptr) {
        HILOGD(TAG, "StartSystemAbility is called for SA:%{public}d", ability->GetSystemAbilitId());
        if (ability->GetDependSa().empty()) {
            //调用SystemAbility::Start()
            ability->Start();
        } else {
            StartDependSaTask(ability);
        }
        HILOGI(TAG, "%{public}s SA:%{public}d init finished, %{public}" PRId64 " ms",
            Str16ToStr8(procName_).c_str(), ability->GetSystemAbilitId(), (GetTickCount() - startBegin_));
    }

    std::lock_guard<std::mutex> lock(startPhaseLock_);
    if (startTaskNum_ > 0) {
        --startTaskNum_;
    }
    startPhaseCV_.notify_one();
}

foundation\systemabilitymgr\safwk\services\safwk\src\system_ability.cpp

//在 Start()方法中会触发钩子函数 OnStart()的调用,OnStart()通常由 SA 自己实现,用来完成其的初始化工作,并调用 Publish()发布 SA。
最后 Publish()方法会调用 samgr 的 AddSystemAbility()方法,将 SA 注册到 samgr 中

void SystemAbility::Start()
{
    // Ensure that the lifecycle is sequentially called by SAMGR
    HILOGD(TAG, "starting system ability...");
    {
        std::lock_guard<std::recursive_mutex> autoLock(abilityLock);
        if (abilityState_ != SystemAbilityState::NOT_LOADED) {
            return;
        }
    }
    HILOGD(TAG, "[PerformanceTest]OnStart SA:%{public}d", saId_);
    int64_t begin = GetTickCount();
    HITRACE_METER_NAME(HITRACE_TAG_SAMGR, ToString(saId_) + "_OnStart");
    nlohmann::json startReason = LocalAbilityManager::GetInstance().GetStartReason(saId_);
    SystemAbilityOnDemandReason onDemandStartReason =
        LocalAbilityManager::GetInstance().JsonToOnDemandReason(startReason);
    GetOnDemandReasonExtraData(onDemandStartReason);
    OnStart(onDemandStartReason);
    std::lock_guard<std::recursive_mutex> autoLock(abilityLock);
    isRunning_ = true;
    HILOGI(TAG, "[PerformanceTest]OnStart SA:%{public}d finished, spend:%{public}" PRId64 " ms",
        saId_, (GetTickCount() - begin));
}

// The details should be implemented by subclass
void SystemAbility::OnStart()
{
}

// The details should be implemented by subclass
void SystemAbility::OnStart(const SystemAbilityOnDemandReason& startReason)
{
    OnStart();
}

// The details should be implemented by subclass
void SystemAbility::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
{
}

......

bool SystemAbility::Publish(sptr<IRemoteObject> systemAbility)
{
    if (systemAbility == nullptr) {
        HILOGE(TAG, "systemAbility is nullptr");
        return false;
    }
    HILOGD(TAG, "[PerformanceTest]Publish SA:%{public}d", saId_);
    // Avoid automatic destruction of system ability caused by failure of publishing ability
    publishObj_ = systemAbility;
    int64_t begin = GetTickCount();
    sptr<ISystemAbilityManager> samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
    if (samgrProxy == nullptr) {
        HILOGE(TAG, "failed to get samgrProxy");
        return false;
    }

    ISystemAbilityManager::SAExtraProp saExtra(GetDistributed(), GetDumpLevel(), capability_, permission_);
    std::lock_guard<std::recursive_mutex> autoLock(abilityLock);
    //调用 samgr 的 AddSystemAbility()方法,将 SA 注册到 samgr 中
    int32_t result = samgrProxy->AddSystemAbility(saId_, publishObj_, saExtra);
    HILOGI(TAG, "[PerformanceTest]Publish SA:%{public}d result:%{public}d, spend:%{public}" PRId64 " ms",
        saId_, result, (GetTickCount() - begin));
    if (result == ERR_OK) {
        abilityState_ = SystemAbilityState::ACTIVE;
        return true;
    }
    return false;
}

foundation\ability\ability_runtime\services\abilitymgr\src\ability_manager_service.cpp

//服务启动完成,可以对外提供服务
void AbilityManagerService::OnStart()
{
    if (state_ == ServiceRunningState::STATE_RUNNING) {
        HILOG_INFO("AMS has already started.");
        return;
    }
    HILOG_INFO("AMS starting.");
    if (!Init()) {
        HILOG_ERROR("Failed to init AMS.");
        return;
    }
    state_ = ServiceRunningState::STATE_RUNNING;
    /* Publish service maybe failed, so we need call this function at the last,
     * so it can't affect the TDD test program */
    instance_ = DelayedSingleton<AbilityManagerService>::GetInstance().get();
    if (instance_ == nullptr) {
        HILOG_ERROR("AMS enter OnStart, but instance_ is nullptr!");
        return;
    }
    bool ret = Publish(instance_);
    if (!ret) {
        HILOG_ERROR("Publish AMS failed!");
        return;
    }

    //投票
    SetParameter(BOOTEVENT_APPFWK_READY.c_str(), "true");
    AddSystemAbilityListener(BACKGROUND_TASK_MANAGER_SERVICE_ID);
    AddSystemAbilityListener(DISTRIBUTED_SCHED_SA_ID);
    AddSystemAbilityListener(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
    HILOG_INFO("AMS start success.");
}

account进程

account在post-init阶段启动
base\account\os_account\services\accountmgr\accountmgr.cfg

"services" : [{
            "name" : "accountmgr",
            "path" : ["/system/bin/sa_main", "/system/profile/accountmgr.json"],
            "permission" : [
                "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED",
                "ohos.permission.GET_RUNNING_INFO",
                "ohos.permission.ENFORCE_USER_IDM",
                "ohos.permission.USE_USER_IDM",
                "ohos.permission.MANAGE_USER_IDM",
                "ohos.permission.ACCESS_USER_AUTH_INTERNAL",
                "ohos.permission.ACCESS_PIN_AUTH",
                "ohos.permission.STORAGE_MANAGER",
                "ohos.permission.securityguard.REPORT_SECURITY_INFO",
                "ohos.permission.DISTRIBUTED_DATASYNC",
                "ohos.permission.RUNNING_STATE_OBSERVER",
                "ohos.permission.PUBLISH_SYSTEM_COMMON_EVENT",
                "ohos.permission.STORAGE_MANAGER_CRYPT"
            ],
            "permission_acls" : [
                "ohos.permission.ENFORCE_USER_IDM",
                "ohos.permission.STORAGE_MANAGER_CRYPT"
            ],
            "uid" : "account",
            "gid" : ["account", "shell", "access_token"],
            "bootevents" : [ "bootevent.account.ready" ],
            "writepid" : [
                "/dev/cpuset/foreground/tasks",
                "/dev/stune/foreground/tasks",
                "/dev/blkio/foreground/tasks"
            ],
            "jobs" : {
                "on-start" : "services:accountmgr"
            },
            "secon" : "u:r:accountmgr:s0"
        }
    ]

base\account\os_account\services\accountmgr\src\account_mgr_service.cpp

//服务启动
void AccountMgrService::OnStart()
{
    if (state_ == ServiceRunningState::STATE_RUNNING) {
        ACCOUNT_LOGI("AccountMgrService has already started.");
        return;
    }

    UpdateTraceLabelAdapter();
    StartTraceAdapter("accountmgr service onstart");
    CountTraceAdapter("activeid", -1);

    PerfStat::GetInstance().SetInstanceStartTime(GetTickCount());
    ACCOUNT_LOGI("start is triggered");
    if (!Init()) {
        ACCOUNT_LOGE("failed to init AccountMgrService");
        FinishTraceAdapter();
        return;
    }
    bool isAccountCompleted = false;
    std::int32_t defaultActivatedId = Constants::START_USER_ID;
    osAccountManagerService_->GetDefaultActivatedOsAccount(defaultActivatedId);
    osAccountManagerService_->IsOsAccountCompleted(defaultActivatedId, isAccountCompleted);
    if (!isAccountCompleted) {
        AddSystemAbilityListener(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
    }
    AddSystemAbilityListener(STORAGE_MANAGER_MANAGER_ID);
    AddSystemAbilityListener(ABILITY_MGR_SERVICE_ID);
    ACCOUNT_LOGI("AccountMgrService::OnStart start service finished.");
    FinishTraceAdapter();

    IPCSkeleton::SetMaxWorkThreadNum(5); // 5: ipc thread num
}

void AccountMgrService::OnStop()
{
    PerfStat::GetInstance().SetInstanceStopTime(GetTickCount());
    ACCOUNT_LOGI("onstop is called");
    IAccountContext::SetInstance(nullptr);
    SelfClean();
}

//addSystemAbility回调
void AccountMgrService::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
{
    ACCOUNT_LOGI("OnAddSystemAbility systemAbilityId %{public}d", systemAbilityId);
    std::lock_guard<std::mutex> lock(statusMutex_);
    switch (systemAbilityId) {
        case STORAGE_MANAGER_MANAGER_ID: {
            isStorageReady_ = true;
            break;
        }
        case ABILITY_MGR_SERVICE_ID: {
            isAmsReady_ = true;
            break;
        }
        case BUNDLE_MGR_SERVICE_SYS_ABILITY_ID: {
            isBmsReady_ = true;
            break;
        }
        default:
            break;
    }

    if (!isStorageReady_) {
        return;
    }

    bool isAccountCompleted = false;
    std::int32_t defaultActivatedId = Constants::START_USER_ID;
    osAccountManagerService_->GetDefaultActivatedOsAccount(defaultActivatedId);
    osAccountManagerService_->IsOsAccountCompleted(defaultActivatedId, isAccountCompleted);
    if (!isAccountCompleted && !isBmsReady_) {
        return;
    }

    if (isAccountCompleted && !isAmsReady_) {
        return;
    }

    //创建基础账户
    osAccountManagerService_->CreateBasicAccounts();
}

base\account\os_account\services\accountmgr\src\osaccount\os_account_manager_service.cpp

void OsAccountManagerService::CreateBasicAccounts()
{
    ACCOUNT_LOGI("enter!");
    //初始化
    innerManager_.Init();
    ACCOUNT_LOGI("exit!");
}

base\account\os_account\services\accountmgr\src\osaccount\inner_os_account_manager.cpp

void IInnerOsAccountManager::Init()
{
    CreateBaseAdminAccount();
    CreateBaseStandardAccount();
    //启动账户
    StartAccount();
#ifdef ENABLE_MULTIPLE_ACTIVE_ACCOUNTS
    RestartActiveAccount();
#endif // ENABLE_MULTIPLE_ACTIVE_ACCOUNTS
    CleanGarbageAccounts();
}

......

void IInnerOsAccountManager::StartAccount()
{
    ACCOUNT_LOGI("start to activate default account");
    ResetAccountStatus();
    OsAccountInfo osAccountInfo;
    ErrCode errCode = osAccountControl_->GetOsAccountInfoById(defaultActivatedId_, osAccountInfo);
    if (errCode != ERR_OK) {
        ACCOUNT_LOGE("account not found, localId: %{public}d, error: %{public}d", defaultActivatedId_, errCode);
        RetryToGetAccount(osAccountInfo);
        defaultActivatedId_ = osAccountInfo.GetLocalId();
        osAccountControl_->SetDefaultActivatedOsAccount(defaultActivatedId_);
    }
    auto task = std::bind(&IInnerOsAccountManager::WatchStartUser, this, defaultActivatedId_);
    std::thread taskThread(task);
    pthread_setname_np(taskThread.native_handle(), WATCH_START_USER);
    taskThread.detach();
    if (!osAccountInfo.GetIsCreateCompleted() && (SendMsgForAccountCreate(osAccountInfo) != ERR_OK)) {
        ACCOUNT_LOGE("account %{public}d not created completely", defaultActivatedId_);
        return;
    }
    // activate
    //传输账号信息
    SendMsgForAccountActivate(osAccountInfo);
}

.....

ErrCode IInnerOsAccountManager::SendMsgForAccountActivate(OsAccountInfo &osAccountInfo)
{
    // activate
    int localId = osAccountInfo.GetLocalId();
    ErrCode errCode = OsAccountInterface::SendToStorageAccountStart(osAccountInfo);
    if (errCode != ERR_OK) {
        ACCOUNT_LOGE("account %{public}d call storage active failed, errCode %{public}d.",
            localId, errCode);
        return ERR_ACCOUNT_COMMON_GET_SYSTEM_ABILITY_MANAGER;
    }
    //通知ams账号启动
    errCode = OsAccountInterface::SendToAMSAccountStart(osAccountInfo);
    if (errCode != ERR_OK) {
        ACCOUNT_LOGE("account %{public}d call ams active failed, errCode %{public}d.",
            localId, errCode);
        return errCode;
    }
    // update info
    osAccountInfo.SetIsActived(true);
    int64_t time =
        std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    osAccountInfo.SetLastLoginTime(time);
    errCode = osAccountControl_->UpdateOsAccount(osAccountInfo);
    if (errCode != ERR_OK) {
        ACCOUNT_LOGE("update %{public}d account info failed, errCode %{public}d.",
            localId, errCode);
        return ERR_OSACCOUNT_SERVICE_INNER_UPDATE_ACCOUNT_ERROR;
    }
    RefreshActiveList(localId);
    //投票
    SetParameter(ACCOUNT_READY_EVENT.c_str(), "true");
    OsAccountInterface::SendToCESAccountSwitched(osAccountInfo);
    subscribeManager_.Publish(localId, OS_ACCOUNT_SUBSCRIBE_TYPE::ACTIVED);
    ACCOUNT_LOGI("SendMsgForAccountActivate ok");
    return errCode;
}

base\account\os_account\services\accountmgr\src\osaccount\os_account_interface.cpp

ErrCode OsAccountInterface::SendToAMSAccountStart(OsAccountInfo &osAccountInfo)
{
    ACCOUNT_LOGI("start");
    StartTraceAdapter("AbilityManagerAdapter StartUser");
    ErrCode code = AbilityManagerAdapter::GetInstance()->StartUser(osAccountInfo.GetLocalId());
    if (code != ERR_OK) {
        ACCOUNT_LOGE("AbilityManagerAdapter StartUser failed! errcode is %{public}d", code);
        ReportOsAccountOperationFail(osAccountInfo.GetLocalId(), Constants::OPERATION_ACTIVATE, code,
            "AbilityManagerAdapter StartUser failed!");
        FinishTraceAdapter();
        return code;
    }
    ACCOUNT_LOGI("end, succeed!");
    FinishTraceAdapter();
    return ERR_OK;
}

base\account\os_account\services\accountmgr\src\ability_manager_adapter\ability_manager_adapter.cpp

ErrCode AbilityManagerAdapter::StartUser(int32_t accountId)
{
    auto abms = GetAbilityManager();
    if (abms == nullptr) {
        ACCOUNT_LOGE("ability manager proxy is nullptr.");
        return ERR_ACCOUNT_COMMON_CONNECT_ABILITY_MANAGER_SERVICE_ERROR;
    }

    int error;
    MessageParcel data;
    MessageParcel reply;
    MessageOption option;

    if (!data.WriteInterfaceToken(ABILITY_MGR_DESCRIPTOR)) {
        ACCOUNT_LOGE("write interface token failed.");
        return INNER_ERR;
    }

    if (!data.WriteInt32(accountId)) {
        ACCOUNT_LOGE("StartUser:WriteInt32 fail.");
        return ERR_INVALID_VALUE;
    }
    //ipc调用startUser
    error = abms->SendRequest(static_cast<uint32_t>(AbilityManagerInterfaceCode::START_USER), data, reply, option);
    if (error != NO_ERROR) {
        ACCOUNT_LOGE("StartUser:SendRequest error: %{public}d", error);
        return error;
    }
    return reply.ReadInt32();
}

foundation\ability\ability_runtime\services\abilitymgr\src\ability_manager_stub.cpp
消息码START_USER对应的函数为StartUserInner();

requestFuncMap_[static_cast<uint32_t>(AbilityManagerInterfaceCode::START_USER)] =
        &AbilityManagerStub::StartUserInner;


......

int AbilityManagerStub::StartUserInner(MessageParcel &data, MessageParcel &reply)
{
    int32_t userId = data.ReadInt32();
    int result = StartUser(userId);
    if (!reply.WriteInt32(result)) {
        HILOG_ERROR("StartUser failed.");
        return ERR_INVALID_VALUE;
    }
    return NO_ERROR;
}

StartUser对应的实现在AbilityManagerStub的实现类AbilityManagerService中
foundation\ability\ability_runtime\services\abilitymgr\src\ability_manager_service.cpp

int AbilityManagerService::StartUser(int userId)
{
    HILOG_DEBUG("%{public}s, userId:%{public}d", __func__, userId);
    //权限验证
    if (IPCSkeleton::GetCallingUid() != ACCOUNT_MGR_SERVICE_UID) {
        HILOG_ERROR("%{public}s: Permission verification failed, not account process", __func__);
        return CHECK_PERMISSION_FAILED;
    }

    if (userController_) {
        return userController_->StartUser(userId, true);
    }
    return 0;
}

foundation\ability\ability_runtime\services\abilitymgr\src\user_controller.cpp

int32_t UserController::StartUser(int32_t userId, bool isForeground)
{
    if (userId < 0 || userId == USER_ID_NO_HEAD) {
        HILOG_ERROR("StartUser userId is invalid:%{public}d", userId);
        return -1;
    }

    if (IsCurrentUser(userId)) {
        HILOG_WARN("StartUser user is already current:%{public}d", userId);
        return 0;
    }

    if (!IsExistOsAccount(userId)) {
        HILOG_ERROR("StartUser not exist such account:%{public}d", userId);
        return -1;
    }

    if (isForeground && GetCurrentUserId() != USER_ID_NO_HEAD && !Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
        // start freezing screen
        SetFreezingNewUserId(userId);
        DelayedSingleton<AbilityManagerService>::GetInstance()->StartFreezingScreen();
    }

    auto oldUserId = GetCurrentUserId();
    auto userItem = GetOrCreateUserItem(userId);
    auto state = userItem->GetState();
    if (state == STATE_STOPPING || state == STATE_SHUTDOWN) {
        HILOG_ERROR("StartUser user is stop now, userId:%{public}d", userId);
        return -1;
    }

    if (isForeground) {
        SetCurrentUserId(userId);
        // notify wms switching now
    }

    bool needStart = false;
    if (state == STATE_BOOTING) {
        needStart = true;
        // send user start msg.
        SendSystemUserStart(userId);
    }

    if (isForeground) {
        SendSystemUserCurrent(oldUserId, userId);
        SendReportUserSwitch(oldUserId, userId, userItem);
        SendUserSwitchTimeout(oldUserId, userId, userItem);
    }

    if (needStart) {
        BroadcastUserStarted(userId);
    }

    UserBootDone(userItem);
    if (isForeground) {
        MoveUserToForeground(oldUserId, userId);
    }

    return 0;
}

......

void UserController::MoveUserToForeground(int32_t oldUserId, int32_t newUserId)
{
    auto manager = DelayedSingleton<AbilityManagerService>::GetInstance();
    if (!manager) {
        return;
    }
    //切到当前用户
    manager->SwitchToUser(oldUserId, newUserId);
    BroadcastUserBackground(oldUserId);
    BroadcastUserForeground(newUserId);
}

foundation\ability\ability_runtime\services\abilitymgr\src\ability_manager_service.cpp

void AbilityManagerService::SwitchToUser(int32_t oldUserId, int32_t userId)
{
    HILOG_INFO("%{public}s, oldUserId:%{public}d, newUserId:%{public}d", __func__, oldUserId, userId);
    SwitchManagers(userId);
    if (!Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
        PauseOldUser(oldUserId);
        ConnectBmsService();
        //启动用户应用
        StartUserApps();
    }
    bool isBoot = oldUserId == U0_USER_ID ? true : false;
    //启动luancher或者开机引导
    StartHighestPriorityAbility(userId, isBoot);
    PauseOldConnectManager(oldUserId);
}

......

void AbilityManagerService::StartUserApps()
{
    if (currentMissionListManager_ && currentMissionListManager_->IsStarted()) {
        HILOG_INFO("missionListManager ResumeManager");
        currentMissionListManager_->ResumeManager();
    }
}

......

void AbilityManagerService::StartHighestPriorityAbility(int32_t userId, bool isBoot)
{
    HILOG_DEBUG("%{public}s", __func__);
    auto bms = GetBundleManager();
    CHECK_POINTER(bms);

    /* Query the highest priority ability or extension ability, and start it. usually, it is OOBE or launcher */
    Want want;
    want.AddEntity(HIGHEST_PRIORITY_ABILITY_ENTITY);
    AppExecFwk::AbilityInfo abilityInfo;
    AppExecFwk::ExtensionAbilityInfo extensionAbilityInfo;
    int attemptNums = 0;
    //查询优先级最高的ability
    while (!IN_PROCESS_CALL(bms->ImplicitQueryInfoByPriority(want,
        AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_DEFAULT, userId,
        abilityInfo, extensionAbilityInfo))) {
        HILOG_INFO("Waiting query highest priority ability info completed.");
        ++attemptNums;
        if (!isBoot && attemptNums > SWITCH_ACCOUNT_TRY) {
            HILOG_ERROR("Query highest priority ability failed.");
            return;
        }
        AbilityRequest abilityRequest;
        usleep(REPOLL_TIME_MICRO_SECONDS);
    }

    if (abilityInfo.name.empty() && extensionAbilityInfo.name.empty()) {
        HILOG_ERROR("Query highest priority ability failed");
        return;
    }

    Want abilityWant; // donot use 'want' here, because the entity of 'want' is not empty
    if (!abilityInfo.name.empty()) {
        /* highest priority ability */
        HILOG_INFO("Start the highest priority ability. bundleName: %{public}s, ability:%{public}s",
            abilityInfo.bundleName.c_str(), abilityInfo.name.c_str());
        abilityWant.SetElementName(abilityInfo.bundleName, abilityInfo.name);
    } else {
        /* highest priority extension ability */
        HILOG_INFO("Start the highest priority extension ability. bundleName: %{public}s, ability:%{public}s",
            extensionAbilityInfo.bundleName.c_str(), extensionAbilityInfo.name.c_str());
        abilityWant.SetElementName(extensionAbilityInfo.bundleName, extensionAbilityInfo.name);
    }

#ifdef SUPPORT_GRAPHICS
    abilityWant.SetParam(NEED_STARTINGWINDOW, false);
    // wait BOOT_ANIMATION_STARTED to start LAUNCHER
    //等待开机动画是否准备好才能继续往下走启动launcher
    WaitBootAnimationStart();
#endif

    /* OOBE APP启动完成之后需要disable自己,否者每次重启都会启动 */
    (void)StartAbility(abilityWant, userId, DEFAULT_INVAL_VALUE);
}

......

void AbilityManagerService::WaitBootAnimationStart()
{
    //判读属性bootevent.bootanimation.ready是否被置为true.
    char value[BOOTEVENT_BOOT_ANIMATION_READY_SIZE] = "";
    int32_t ret = GetParameter(BOOTEVENT_BOOT_ANIMATION_READY.c_str(), "", value,
        BOOTEVENT_BOOT_ANIMATION_READY_SIZE);
    if (ret > 0 && !std::strcmp(value, "false")) {
        // Get new param success and new param is not ready, wait the new param.
        WaitParameter(BOOTEVENT_BOOT_ANIMATION_READY.c_str(), "true",
            AmsConfigurationParameter::GetInstance().GetBootAnimationTimeoutTime());
    } else if (ret <= 0 || !std::strcmp(value, "")) {
        // Get new param failed or new param is not set, wait the old param.
        WaitParameter(BOOTEVENT_BOOT_ANIMATION_STARTED.c_str(), "true",
            AmsConfigurationParameter::GetInstance().GetBootAnimationTimeoutTime());
    }
    // other, the animation is ready, not wait.
}

......

std::shared_ptr<AppExecFwk::BundleMgrHelper> AbilityManagerService::GetBundleManager()
{
    if (bundleMgrHelper_ == nullptr) {
        bundleMgrHelper_ = AbilityUtil::GetBundleManagerHelper();
    }
    return bundleMgrHelper_;
}

至此launcher或者开机引导(OOBE)就启动完成。
foundation\ability\ability_runtime\frameworks\native\appkit\ability_bundle_manager_helper\bundle_mgr_helper.cpp

bool BundleMgrHelper::ImplicitQueryInfoByPriority(
    const Want &want, int32_t flags, int32_t userId, AbilityInfo &abilityInfo, ExtensionAbilityInfo &extensionInfo)
{
    HILOG_DEBUG("Called.");
    //绑定服务BundleMgrService
    auto bundleMgr = Connect();
    if (bundleMgr == nullptr) {
        HILOG_ERROR("Failed to connect.");
        return false;
    }

    //调用包管理服务的ImplicitQueryInfoByPriority
    return bundleMgr->ImplicitQueryInfoByPriority(want, flags, userId, abilityInfo, extensionInfo);
}

......

sptr<IBundleMgr> BundleMgrHelper::Connect()
{
    HILOG_DEBUG("Called.");
    std::lock_guard<std::mutex> lock(mutex_);
    if (bundleMgr_ == nullptr) {
        sptr<ISystemAbilityManager> systemAbilityManager =
            SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
        if (systemAbilityManager == nullptr) {
            HILOG_ERROR("Failed to get system ability manager.");
            return nullptr;
        }

        sptr<IRemoteObject> remoteObject_ = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
        if (remoteObject_ == nullptr || (bundleMgr_ = iface_cast<IBundleMgr>(remoteObject_)) == nullptr) {
            HILOG_ERROR("Failed to get bundle mgr service remote object.");
            return nullptr;
        }
        std::weak_ptr<BundleMgrHelper> weakPtr = shared_from_this();
        auto deathCallback = [weakPtr](const wptr<IRemoteObject>& object) {
            auto sharedPtr = weakPtr.lock();
            if (sharedPtr == nullptr) {
                HILOG_ERROR("Bundle helper instance is nullptr.");
                return;
            }
            sharedPtr->OnDeath();
        };
        deathRecipient_ = new (std::nothrow) BundleMgrServiceDeathRecipient(deathCallback);
        if (deathRecipient_ == nullptr) {
            HILOG_ERROR("Failed to create death recipient ptr deathRecipient_!");
            return nullptr;
        }
        if (bundleMgr_->AsObject() != nullptr) {
            bundleMgr_->AsObject()->AddDeathRecipient(deathRecipient_);
        }
    }

    return bundleMgr_;
}

foundation\bundlemanager\bundle_framework\interfaces\inner_api\appexecfwk_core\src\bundlemgr\bundle_mgr_proxy.cpp

bool BundleMgrProxy::ImplicitQueryInfoByPriority(const Want &want, int32_t flags, int32_t userId,
    AbilityInfo &abilityInfo, ExtensionAbilityInfo &extensionInfo)
{
    APP_LOGD("begin to ImplicitQueryInfoByPriority");
    HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
    MessageParcel data;
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        APP_LOGE("fail to implicit query info by priority due to write MessageParcel fail");
        return false;
    }
    if (!data.WriteParcelable(&want)) {
        APP_LOGE("fail to implicit query info by priority due to write want fail");
        return false;
    }
    if (!data.WriteInt32(flags)) {
        APP_LOGE("fail to implicit query info by priority due to write flags fail");
        return false;
    }
    if (!data.WriteInt32(userId)) {
        APP_LOGE("fail to implicit query info by priority due to write userId error");
        return false;
    }

    MessageParcel reply;
    //将消息码和对应的数据发给服务端
    if (!SendTransactCmd(BundleMgrInterfaceCode::IMPLICIT_QUERY_INFO_BY_PRIORITY, data, reply)) {
        return false;
    }

    if (!reply.ReadBool()) {
        APP_LOGE("reply result false");
        return false;
    }

    std::unique_ptr<AbilityInfo> abilityInfoPtr(reply.ReadParcelable<AbilityInfo>());
    if (abilityInfoPtr == nullptr) {
        APP_LOGE("read AbilityInfo failed");
        return false;
    }
    abilityInfo = *abilityInfoPtr;

    std::unique_ptr<ExtensionAbilityInfo> extensionInfoPtr(reply.ReadParcelable<ExtensionAbilityInfo>());
    if (extensionInfoPtr == nullptr) {
        APP_LOGE("read ExtensionAbilityInfo failed");
        return false;
    }
    extensionInfo = *extensionInfoPtr;
    return true;
}

foundation\bundlemanager\bundle_framework\interfaces\inner_api\appexecfwk_core\src\bundlemgr\bundle_mgr_host.cpp

//消息码对应的函数
funcMap_.emplace(static_cast<uint32_t>(BundleMgrInterfaceCode::IMPLICIT_QUERY_INFO_BY_PRIORITY),
        &BundleMgrHost::HandleImplicitQueryInfoByPriority);

......

ErrCode BundleMgrHost::HandleImplicitQueryInfoByPriority(MessageParcel &data, MessageParcel &reply)
{
    HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
    std::unique_ptr<Want> want(data.ReadParcelable<Want>());
    if (want == nullptr) {
        APP_LOGE("ReadParcelable<want> failed");
        return ERR_APPEXECFWK_PARCEL_ERROR;
    }
    int32_t flags = data.ReadInt32();
    int32_t userId = data.ReadInt32();
    AbilityInfo abilityInfo;
    ExtensionAbilityInfo extensionInfo;
    bool ret = ImplicitQueryInfoByPriority(*want, flags, userId, abilityInfo, extensionInfo);
    if (!reply.WriteBool(ret)) {
        APP_LOGE("write failed");
        return ERR_APPEXECFWK_PARCEL_ERROR;
    }
    if (ret) {
        if (!reply.WriteParcelable(&abilityInfo)) {
            APP_LOGE("write AbilityInfo failed");
            return ERR_APPEXECFWK_PARCEL_ERROR;
        }
        if (!reply.WriteParcelable(&extensionInfo)) {
            APP_LOGE("write ExtensionAbilityInfo failed");
            return ERR_APPEXECFWK_PARCEL_ERROR;
        }
    }
    return ERR_OK;
}

foundation\bundlemanager\bundle_framework\services\bundlemgr\src\bundle_mgr_host_impl.cpp

//ImplicitQueryInfoByPriority函数对应的服务端实现
bool BundleMgrHostImpl::ImplicitQueryInfoByPriority(const Want &want, int32_t flags, int32_t userId,
    AbilityInfo &abilityInfo, ExtensionAbilityInfo &extensionInfo)
{
    APP_LOGD("start ImplicitQueryInfoByPriority, flags : %{public}d, userId : %{public}d", flags, userId);
    //判断是否是系统应用以及sdk版本号是否为9
    if (!BundlePermissionMgr::IsSystemApp() &&
        !BundlePermissionMgr::VerifyCallingBundleSdkVersion(Constants::API_VERSION_NINE)) {
        APP_LOGD("non-system app calling system api");
        return true;
    }
    //判断是否有对应的权限
    if (!BundlePermissionMgr::VerifyCallingPermissionsForAll({Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED,
        Constants::PERMISSION_GET_BUNDLE_INFO}) &&
        !BundlePermissionMgr::IsBundleSelfCalling(want.GetElement().GetBundleName())) {
        APP_LOGE("verify permission failed");
        return false;
    }
    auto dataMgr = GetDataMgrFromService();
    if (dataMgr == nullptr) {
        APP_LOGE("DataMgr is nullptr");
        return false;
    }
    return dataMgr->ImplicitQueryInfoByPriority(want, flags, userId, abilityInfo, extensionInfo);
}

foundation\bundlemanager\bundle_framework\services\bundlemgr\src\bundle_data_mgr.cpp

bool BundleDataMgr::ImplicitQueryInfoByPriority(const Want &want, int32_t flags, int32_t userId,
    AbilityInfo &abilityInfo, ExtensionAbilityInfo &extensionInfo) const
{
    int32_t requestUserId = GetUserId(userId);
    if (requestUserId == Constants::INVALID_USERID) {
        APP_LOGW("invalid userId");
        return false;
    }
    //查询对应的abilityInfos和extensionInfos
    std::vector<AbilityInfo> abilityInfos;
    bool abilityValid =
        ImplicitQueryAbilityInfos(want, flags, requestUserId, abilityInfos) && (abilityInfos.size() > 0);
    std::vector<ExtensionAbilityInfo> extensionInfos;
    bool extensionValid =
        ImplicitQueryExtensionInfos(want, flags, requestUserId, extensionInfos) && (extensionInfos.size() > 0);
    if (!abilityValid && !extensionValid) {
        // both invalid
        APP_LOGW("can't find target AbilityInfo or ExtensionAbilityInfo");
        return false;
    }
    if (abilityValid && extensionValid) {
        // both valid
        if (abilityInfos[0].priority >= extensionInfos[0].priority) {
            APP_LOGD("find target AbilityInfo with higher priority, name : %{public}s", abilityInfos[0].name.c_str());
            abilityInfo = abilityInfos[0];
        } else {
            APP_LOGD("find target ExtensionAbilityInfo with higher priority, name : %{public}s",
                extensionInfos[0].name.c_str());
            extensionInfo = extensionInfos[0];
        }
    } else if (abilityValid) {
        // only ability valid
        APP_LOGD("find target AbilityInfo, name : %{public}s", abilityInfos[0].name.c_str());
        abilityInfo = abilityInfos[0];
    } else {
        // only extension valid
        APP_LOGD("find target ExtensionAbilityInfo, name : %{public}s", extensionInfos[0].name.c_str());
        extensionInfo = extensionInfos[0];
    }
    return true;
}

......

bool BundleDataMgr::ImplicitQueryAbilityInfos(
    const Want &want, int32_t flags, int32_t userId, std::vector<AbilityInfo> &abilityInfos, int32_t appIndex) const
{
    int32_t requestUserId = GetUserId(userId);
    if (requestUserId == Constants::INVALID_USERID) {
        return false;
    }
    //开机启动的时候传进来的entity为HIGHEST_PRIORITY_ABILITY_ENTITY
    if (want.GetAction().empty() && want.GetEntities().empty()
        && want.GetUriString().empty() && want.GetType().empty()) {
        APP_LOGE("param invalid");
        return false;
    }
    APP_LOGD("action:%{public}s, uri:%{private}s, type:%{public}s",
        want.GetAction().c_str(), want.GetUriString().c_str(), want.GetType().c_str());
    APP_LOGD("flags:%{public}d, userId:%{public}d", flags, userId);
    std::shared_lock<std::shared_mutex> lock(bundleInfoMutex_);
    if (bundleInfos_.empty()) {
        APP_LOGW("bundleInfos_ is empty");
        return false;
    }
    //开机启动的时候没有设置bundleName,所以为empty
    std::string bundleName = want.GetElement().GetBundleName();
    if (!bundleName.empty()) {
        // query in current bundleName
        if (!ImplicitQueryCurAbilityInfos(want, flags, requestUserId, abilityInfos, appIndex)) {
            APP_LOGD("ImplicitQueryCurAbilityInfos failed, bundleName: %{public}s", bundleName.c_str());
            return false;
        }
    } else {
        // query all
        ImplicitQueryAllAbilityInfos(want, flags, requestUserId, abilityInfos, appIndex);
    }
    // sort by priority, descending order.
    //根据proority做排序
    if (abilityInfos.size() > 1) {
        std::stable_sort(abilityInfos.begin(), abilityInfos.end(),
            [](AbilityInfo a, AbilityInfo b) { return a.priority > b.priority; });
    }
    return true;
}

......

void BundleDataMgr::ImplicitQueryAllAbilityInfos(const Want &want, int32_t flags, int32_t userId,
    std::vector<AbilityInfo> &abilityInfos, int32_t appIndex) const
{
    APP_LOGD("begin to ImplicitQueryAllAbilityInfos.");
    int32_t requestUserId = GetUserId(userId);
    if (requestUserId == Constants::INVALID_USERID) {
        APP_LOGW("invalid userId");
        return;
    }

    // query from bundleInfos_
    if (appIndex == 0) {
        for (const auto &item : bundleInfos_) {
            const InnerBundleInfo &innerBundleInfo = item.second;
            int32_t responseUserId = innerBundleInfo.GetResponseUserId(requestUserId);
            if (CheckInnerBundleInfoWithFlags(innerBundleInfo, flags, responseUserId) != ERR_OK) {
                APP_LOGD("ImplicitQueryAllAbilityInfos failed, bundleName:%{public}s, responseUserId:%{public}d",
                    innerBundleInfo.GetBundleName().c_str(), responseUserId);
                continue;
            }

            GetMatchAbilityInfos(want, flags, innerBundleInfo, responseUserId, abilityInfos);
        }
    } else {
        // query from sandbox manager for sandbox bundle
        if (sandboxAppHelper_ == nullptr) {
            APP_LOGW("sandboxAppHelper_ is nullptr");
            return;
        }
        auto sandboxMap = sandboxAppHelper_->GetSandboxAppInfoMap();
        for (const auto &item : sandboxMap) {
            InnerBundleInfo info;
            size_t pos = item.first.rfind(Constants::FILE_UNDERLINE);
            if (pos == std::string::npos) {
                APP_LOGD("sandbox map contains invalid element");
                continue;
            }
            std::string innerBundleName = item.first.substr(pos + 1);
            if (sandboxAppHelper_->GetSandboxAppInfo(innerBundleName, appIndex, userId, info) != ERR_OK) {
                APP_LOGD("obtain innerBundleInfo of sandbox app failed");
                continue;
            }

            int32_t responseUserId = info.GetResponseUserId(userId);
            GetMatchAbilityInfos(want, flags, info, responseUserId, abilityInfos);
        }
    }
    APP_LOGD("finish to ImplicitQueryAllAbilityInfos.");
}

void BundleDataMgr::GetMatchAbilityInfos(const Want &want, int32_t flags,
    const InnerBundleInfo &info, int32_t userId, std::vector<AbilityInfo> &abilityInfos) const
{
    if ((static_cast<uint32_t>(flags) & GET_ABILITY_INFO_SYSTEMAPP_ONLY) == GET_ABILITY_INFO_SYSTEMAPP_ONLY &&
        !info.IsSystemApp()) {
        return;
    }
    std::map<std::string, std::vector<Skill>> skillInfos = info.GetInnerSkillInfos();
    for (const auto &abilityInfoPair : info.GetInnerAbilityInfos()) {
        bool isPrivateType = MatchPrivateType(
            want, abilityInfoPair.second.supportExtNames, abilityInfoPair.second.supportMimeTypes);
        auto skillsPair = skillInfos.find(abilityInfoPair.first);
        if (skillsPair == skillInfos.end()) {
            continue;
        }
        for (const Skill &skill : skillsPair->second) {
            if (isPrivateType || skill.Match(want)) {
                AbilityInfo abilityinfo = abilityInfoPair.second;
                AddAbilitySkillUrisInfo(flags, skill, abilityinfo);
                if (abilityinfo.name == Constants::APP_DETAIL_ABILITY) {
                    continue;
                }
                if (!(static_cast<uint32_t>(flags) & GET_ABILITY_INFO_WITH_DISABLE)) {
                    if (!info.IsAbilityEnabled(abilityinfo, GetUserId(userId))) {
                        APP_LOGW("GetMatchAbilityInfos %{public}s is disabled", abilityinfo.name.c_str());
                        continue;
                    }
                }
                if ((static_cast<uint32_t>(flags) & GET_ABILITY_INFO_WITH_APPLICATION) ==
                    GET_ABILITY_INFO_WITH_APPLICATION) {
                    info.GetApplicationInfo(
                        ApplicationFlag::GET_APPLICATION_INFO_WITH_CERTIFICATE_FINGERPRINT, userId,
                        abilityinfo.applicationInfo);
                }
                if ((static_cast<uint32_t>(flags) & GET_ABILITY_INFO_WITH_PERMISSION) !=
                    GET_ABILITY_INFO_WITH_PERMISSION) {
                    abilityinfo.permissions.clear();
                }
                if ((static_cast<uint32_t>(flags) & GET_ABILITY_INFO_WITH_METADATA) != GET_ABILITY_INFO_WITH_METADATA) {
                    abilityinfo.metaData.customizeData.clear();
                    abilityinfo.metadata.clear();
                }
                abilityInfos.emplace_back(abilityinfo);
                break;
            }
        }
    }
}

void BundleDataMgr::AddAbilitySkillUrisInfo(int32_t flags, const Skill &skill, AbilityInfo &abilityInfo) const
{
    if ((static_cast<uint32_t>(flags) & GET_ABILITY_INFO_WITH_SKILL_URI) == GET_ABILITY_INFO_WITH_SKILL_URI) {
        std::vector<SkillUriForAbilityAndExtension> skillUriTmp;
        for (const SkillUri &uri : skill.uris) {
            SkillUriForAbilityAndExtension skillinfo;
            skillinfo.scheme = uri.scheme;
            skillinfo.host = uri.host;
            skillinfo.port = uri.port;
            skillinfo.path = uri.path;
            skillinfo.pathStartWith = uri.pathStartWith;
            skillinfo.pathRegex = uri.pathRegex;
            skillinfo.type = uri.type;
            skillinfo.utd = uri.utd;
            skillinfo.maxFileSupported = uri.maxFileSupported;
            skillUriTmp.emplace_back(skillinfo);
        }
        abilityInfo.skillUri = skillUriTmp;
    }
}
AbilityInfo> &abilityInfos) const
{
    if ((static_cast<uint32_t>(flags) & GET_ABILITY_INFO_SYSTEMAPP_ONLY) == GET_ABILITY_INFO_SYSTEMAPP_ONLY &&
        !info.IsSystemApp()) {
        return;
    }
    std::map<std::string, std::vector<Skill>> skillInfos = info.GetInnerSkillInfos();
    for (const auto &abilityInfoPair : info.GetInnerAbilityInfos()) {
        bool isPrivateType = MatchPrivateType(
            want, abilityInfoPair.second.supportExtNames, abilityInfoPair.second.supportMimeTypes);
        auto skillsPair = skillInfos.find(abilityInfoPair.first);
        if (skillsPair == skillInfos.end()) {
            continue;
        }
        for (const Skill &skill : skillsPair->second) {
            if (isPrivateType || skill.Match(want)) {
                AbilityInfo abilityinfo = abilityInfoPair.second;
                AddAbilitySkillUrisInfo(flags, skill, abilityinfo);
                if (abilityinfo.name == Constants::APP_DETAIL_ABILITY) {
                    continue;
                }
                if (!(static_cast<uint32_t>(flags) & GET_ABILITY_INFO_WITH_DISABLE)) {
                    if (!info.IsAbilityEnabled(abilityinfo, GetUserId(userId))) {
                        APP_LOGW("GetMatchAbilityInfos %{public}s is disabled", abilityinfo.name.c_str());
                        continue;
                    }
                }
                if ((static_cast<uint32_t>(flags) & GET_ABILITY_INFO_WITH_APPLICATION) ==
                    GET_ABILITY_INFO_WITH_APPLICATION) {
                    info.GetApplicationInfo(
                        ApplicationFlag::GET_APPLICATION_INFO_WITH_CERTIFICATE_FINGERPRINT, userId,
                        abilityinfo.applicationInfo);
                }
                if ((static_cast<uint32_t>(flags) & GET_ABILITY_INFO_WITH_PERMISSION) !=
                    GET_ABILITY_INFO_WITH_PERMISSION) {
                    abilityinfo.permissions.clear();
                }
                if ((static_cast<uint32_t>(flags) & GET_ABILITY_INFO_WITH_METADATA) != GET_ABILITY_INFO_WITH_METADATA) {
                    abilityinfo.metaData.customizeData.clear();
                    abilityinfo.metadata.clear();
                }
                abilityInfos.emplace_back(abilityinfo);
                break;
            }
        }
    }
}

void BundleDataMgr::AddAbilitySkillUrisInfo(int32_t flags, const Skill &skill, AbilityInfo &abilityInfo) const
{
    if ((static_cast<uint32_t>(flags) & GET_ABILITY_INFO_WITH_SKILL_URI) == GET_ABILITY_INFO_WITH_SKILL_URI) {
        std::vector<SkillUriForAbilityAndExtension> skillUriTmp;
        for (const SkillUri &uri : skill.uris) {
            SkillUriForAbilityAndExtension skillinfo;
            skillinfo.scheme = uri.scheme;
            skillinfo.host = uri.host;
            skillinfo.port = uri.port;
            skillinfo.path = uri.path;
            skillinfo.pathStartWith = uri.pathStartWith;
            skillinfo.pathRegex = uri.pathRegex;
            skillinfo.type = uri.type;
            skillinfo.utd = uri.utd;
            skillinfo.maxFileSupported = uri.maxFileSupported;
            skillUriTmp.emplace_back(skillinfo);
        }
        abilityInfo.skillUri = skillUriTmp;
    }
}

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

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

相关文章

bat脚本banenr

飞出个未来班得 echo off echo .-. echo ( ) echo - echo J L echo ^| ^| echo J L echo ^| ^| echo J L echo …

MySQL-表相关(DDL DML)

文章目录 表的基本操作表的创建表的删除 MySQL中的数据类型整数类型浮点数类型定点数类型日期和时间类型字符串类型charvarchartext 二进制类型 DDL语句查看建表语句修改表名新增字段修改字段(名类型)修改字段(仅类型)删除字段 DML语句insert 增delete 删truncate 语句update 改…

前端学习-CSS的三大特性(十七)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 层叠性 继承性 行高的继承性 优先级 优先级注意点 权重叠加 总结 前言 引入css特性的学习 CSS 有三个非常重要的三个特性:层叠性、继承性、优先级。 层叠…

Android 第5种启动模式:singleInstancePerTask

Android 第5种启动模式&#xff1a;singleInstancePerTask 随着 Android 版本的更新&#xff0c;应用启动模式逐渐丰富。在 Android 12 中&#xff0c;新增了一种启动模式——singleInstancePerTask。它是继 standard、singleTop、singleTask 和 singleInstance 之后的第五种启…

纯css 轮播图片,鼠标移入暂停 移除继续

核心 滚动&#xff1a; animation: 动画名称 20s linear infinite normal;停止&#xff1a; animation: 动画名称 20s linear infinite paused; 完整例子&#xff1a; html: <div class"carousel-wrapper"><div class"carousel"><div cl…

chrome浏览器映射端口

chrome://inspect/#devices 方法2

mysql主从复制及故障修复

一、主MySQL数据库的配置 分别在三台主机&#xff08;chen2/10.110、chen3/10.120、chen4/10.130)中安装mysql数据&#xff0c;其中chen2/10.110作为主MySQL服务器&#xff0c;其余两台作为从MySQL服务器。 1、在主机上部署mysql数据库 详细的请看上一篇&#xff1a;mysql数据…

NewStarCTF2024-Week2-Web-WP

目录 1、复读机 2、你能在一秒内打出八句英文吗 3、遗失的拉链 4、谢谢皮蛋 plus 5、PangBai 过家家&#xff08;2&#xff09; 1、复读机 测了下存在 ssti 没什么说的 fenjing 秒了 2、你能在一秒内打出八句英文吗 每次出来的需要提交的内容都不一样 exp&#xff1a; …

CUDA 全局内存

全局内存在片外。 特点是&#xff1a;容量最大、延迟最大、使用最多 全局内存中的数据是所有线程可见的&#xff0c;Host端可见&#xff0c;且具有与程序相同的生命周期 动态全局内存 主机代码使用CUDA运行时API &#xff1a; cudaMalloc 声明内存空间&#xff1b; cudaFree…

MySQL【知识改变命运】07

MySQL 1&#xff1a;Group by 分组查询1.1&#xff1a;语法&#xff1a;1.2&#xff1a;练习 2&#xff1a;having⼦句3回顾&#xff1a;3&#xff1a;内置函数3.1 :⽇期函数 1&#xff1a;Group by 分组查询 可以根据某列&#xff0c;进行分组查询&#xff0c;比如学校里面的…

基于cloudreve(Docker应用)搭建网盘服务,用于目录的分享和在线预览。

文章目录 I 基于cloudreve(Docker应用)搭建网盘服务安装主要功能设置角色最大容量II 知识扩展:网盘类的文件预览需求背景: iOS可以直接预览PDF等常见格式文件,但是Android浏览器需要先下载文件,才能查看文件内容,因此需要搭建支持目录的分享和在线预览的MinIO文件服务提供…

数据安全存储系统的概念与原理

数据安全存储系统是一种综合性的数据保护方案&#xff0c;旨在确保数据的完整性、保密性和可用性。以下是对数据安全存储系统的详细介绍&#xff1a; 一、概念与原理 数据安全存储系统通过硬件、软件和网络等多个层面的保护措施&#xff0c;防止未经授权的访问、避免数据丢失或…

【MySQL 保姆级教学】表结构的操作(4)

表结构的操作 1. 定义和语法2. 创建表 CREATE2.1 创建表的本质2.2 表的存储引擎2.3 表的字符集和校验规则2.4 创建表实例 3. 查看表结构 DESC3.1 作用3.2 示例 4. 修改表结构 ALTER4.1 添加列 ADD4.2 修改列 MODIFY4.3 删除列 DROP4.4 更改列名 CHANGE 5. 修改表名 RENAME6. 删…

一次性解决vue3引入@jiaminghi/data-view需要手动修改node_modules下文件

修改文件1&#xff1a;node_modules\jiaminghi\data-view\lib\components\decoration6\src\main.vue 修改文件2&#xff1a; node_modules\jiaminghi\data-view\lib\components\decoration3\src\main.vue 修改前&#xff1a; 修改后&#xff1a; 通过打补丁的方式对引用库进行…

【自动驾驶】控制算法(十二)横纵向综合控制 | 从理论到实战全面解析

写在前面&#xff1a; &#x1f31f; 欢迎光临 清流君 的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落。&#x1f4dd; 个人主页&#xff1a;清流君_CSDN博客&#xff0c;期待与您一同探索 移动机器人 领域的无限可能。 &#x1f50d; 本文系 清流君 原创之作&…

Maven与Gradle的区别

Maven与Gradle是两种流行的构建工具&#xff0c;广泛用于Java项目的管理和构建。以下是它们的对比&#xff0c;包括官网、Windows 11配置环境、在IDEA中的相同点和不同点&#xff0c;以及它们各自的优缺点。 官网 Maven官网: https://maven.apache.orgGradle官网: https://gr…

将爱传递 将“服务好”延伸

从泰康客户,转身成为泰康人,她直言是因为亲身感受了泰康“服务好”的魅力。 入司已8年的泰康养老浙江分公司HWP何英英,是泰康“服务好”的受益者。她从朋友的理赔中见证了泰康服务好的温度与力量,又被泰康养老的职域模式所吸引选择加入泰康。如今,她全身心投入在服务的第一线,…

2024软考网络工程师笔记 - 第4章.局域网和城域网

文章目录 局域网基础1️⃣局域网和城域网体系架构 IEEE&#xff08;负责链路层&#xff09;2️⃣局域网拓扑结构 &#x1f551;CSMA/CD1️⃣CSMA/CD2️⃣CSMA/CD三种监听算法3️⃣冲突检测原理 &#x1f552;二进制指数退避算法1️⃣ 二进制指数退避算法 &#x1f553;最小帧长…

分库分表方式介绍

分库分表方式 分库分表包括分库和分表两个部分&#xff0c;在生产中通常包括&#xff1a;垂直分库、水平分库、垂直分表、水平分表四种方式&#xff1b; 1、垂直分表 1.1 垂直分表定义 垂直分表就是在同一数据库内将一张表按照指定字段分成若干表&#xff0c;每张表仅存储其…

RabbitMQ是什么?

了解MQ 消息队列&#xff08;MQ&#xff09;是一种用于异步通信的通信机制&#xff0c;通过将消息存储在队列中以实现系统之间的解耦。MQ 的主要功能是异步传递消息&#xff0c;允许发送者将消息发送到队列中&#xff0c;而接收者可以在适当的时候从队列中读取消息。MQ 常用于…