鸿蒙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.img NA 内核和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传递关键信息给内核,这一部分内容是与平台相关的,主要信息如下:

    名称 示例 说明
    initrd 0x84000000,0x292e00 参考内核文档。 ramfs-rootfs-initramfs.rst initrd.rst
    init /init
    blkdevparts mmcblk0:1M(boot),15M(kernel),200M(system),200M(vendor), 2M(misc),20M(updater),-(userdata) 分区表信息,kernel会根据此信息创建物理分区。
    hardware Hi3516DV300、rk3568等 (必要信息)硬件平台。
    root /dev/ram0(Hi3516DV00)、root=PARTUUID=614e0000-0000 rw(rk3568) kernel加载的启动设备。
    rootfstype ext4 根文件系统类型。
    default_boot_device soc/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;
    }
}
相关推荐
pyliumy25 分钟前
ansible 剧本模式
linux·运维·ansible
威哥爱编程44 分钟前
25个Linux系统性能调优技巧
linux·操作系统
Shaoxi Zhang1 小时前
华为S5735交换机配置脚本
网络·华为
东城绝神1 小时前
《Linux运维总结:基于ARM64+X86_64架构CPU使用docker-compose一键离线部署mongodb 7.0.14容器版分片集群》
linux·运维·mongodb·架构
义一1 小时前
华为---Super VLAN简介及示例配置
华为
手心里的白日梦1 小时前
Linux的环境与历史
linux·运维·服务器
头真的要秃啦1 小时前
Linux SSH服务
linux·服务器·ssh
威桑1 小时前
Linux 下 poll 详解
linux·运维·服务器
哦豁灬1 小时前
linux 终端快捷键常用操作
linux·vim
还下着雨ZG1 小时前
Linux:文件的状态和属性
linux