# 启动恢复 ## 简介 启动恢复负责在内核启动之后到应用启动之前的系统关键进程和服务的启动过程。涉及以下模块: - init启动引导 支持使用LiteOS-A内核的平台,当前包括:Hi3516DV300平台和Hi3518EV300平台。 负责处理从内核加载第一个用户态进程开始,到第一个应用程序启动之间的系统服务进程启动过程。启动恢复子系统除负责加载各系统关键进程之外,还需在启动的同时设置其对应权限,并在子进程启动后对指定进程实行保活(若进程意外退出要重新启动),对于特殊进程意外退出时,启动恢复子系统还要执行系统复位操作。 - appspawn应用孵化 支持使用LiteOS-A内核的平台,当前包括:Hi3516DV300平台和Hi3518EV300平台。 负责接受应用程序框架的命令孵化应用进程,设置其对应权限,并调用应用程序框架的入口。 - bootstrap启动服务模块 支持使用LiteOS-M内核的平台,当前包括:Hi3861平台。 提供了各服务和功能的启动入口标识。在SAMGR启动时,会调用boostrap标识的入口函数,并启动系统服务。 - 系统属性 支持使用LiteOS-M内核和LiteOS-A内核的平台,包括:Hi3861平台,Hi3516DV300平台,Hi3518EV300平台。 负责提供获取与设置操作系统相关的系统属性。 系统属性包括:默认系统属性、OEM厂商系统属性和自定义系统属性。OEM厂商部分仅提供默认值,具体值需OEM产品方按需进行调整,详见“使用”部分。 ## 目录 **表 1** 启动恢复源代码目录结构

名称

描述

适配平台

base/startup/services/appspawn_lite

应用孵化模块,appspawn进程,负责通过IPC机制接收Ability Manager Service的消息,然后根据消息解析结果启动应用进程并赋予其对应权限。

Hi3516DV300

Hi3518EV300

base/startup/services/bootstrap_lite

服务启动模块,启动系统核心服务外的其他服务。

Hi3861

base/startup/services/init_lite

启动引导模块,init进程,内核完成初始化后加载的第一个用户态进程,启动后解析/etc/init.cfg配置文件,并根据解析结果拉起其他系统关键进程,同时分别赋予其对应权限。

Hi3516DV300

Hi3518EV300

base/startup/interfaces

服务启动模块对外接口,由main函数来调用,启动服务框架。

Hi3861

Hi3516DV300

Hi3518EV300

base/startup/frameworks/syspara_lite

系统属性模块。提供获取设备信息接口,如:产品名、品牌名、品类名、厂家名等。

``` base ├──startup 启动恢复子系统根目录 ├──── frameworks │ └── syspara_lite │ ├── LICENSE 开源LICENSE文件 │ ├── parameter 系统属性模块源文件目录 │ │ ├── BUILD.gn │ │ └── src │ │ ├── BUILD.gn │ │ ├── param_impl_hal 系统属性模块基于LiteOS-M核实现 │ │ └── param_impl_posix 系统属性模块基于LiteOS-A核实现 │ └── token │ ├── BUILD.gn │ └── src │ ├── token_impl_hal │ └── token_impl_posix ├──── hals │ └── syspara_lite 系统属性模块硬件抽象层头文件目录 ├──── interfaces │ └── kits │ └── syspara_lite 系统属性模块对外接口目录 └──── services ├── appspawn_lite 应用孵化模块 │ ├── BUILD.gn 应用孵化模块编译配置 │ ├── include 应用孵化模块头文件目录 │ ├── LICENSE 开源LICENSE文件 │ ├── moduletest 应用孵化模块自测试代码目录 │ └── src 应用孵化模块源文件目录 ├── bootstrap_lite 启动服务模块 │ ├── BUILD.gn 启动服务模块编译配置 │ ├── LICENSE 开源LICENSE文件 │ └── source 启动服务模块源文件目录 └── init_lite 启动引导模块 ├── BUILD.gn 启动引导模块编译配置 ├── include 启动引导模块头文件目录 ├── LICENSE 开源LICENSE文件 ├── moduletest 启动引导模块自测试代码目录 └── src 启动引导模块源文件目录 vendor └──huawei └──camera └──init_configs 启动引导模块配置文件目录(json格式,部署于/etc/目录下) ``` ## 约束 启动恢复使用C语言开发。 - 系统属性:OEM厂商相关仅提供默认值,具体值需产品方按需进行调整。 ## 使用 - init启动引导的配置文件 启动引导模块配置文件包含了所有需要由init进程启动的系统关键服务的服务名、可执行文件路径、权限和其他属性信息,该文件位于代码仓库/vendor/huawei/camera/init\_configs/目录,部署在/etc/下,文件名称为init.cfg,采用json格式,文件大小目前限制在100KB以内。 init进程启动后首先读取/etc/init.cfg,然后解析其json内容,并根据解析结果依次加载系统服务。配置文件格式和内容说明如下所示: ``` { "jobs" : [{ "name" : "pre-init", -------- 在init之前执行的job,可以放置一些启动进程之前的预操作(如新建文件夹等) "cmds" : [ -------- 当前job支持的命令集合(当前cmd仅支持start/mkdir/chmod/chown/mount) -------- 命令名称和参数(长度<=128字节)之间有且只能有一个空格 "mkdir /testdir", -------- 创建文件夹命令,mkdir和目标文件夹之间有且只能有一个空格 "chmod 0700 /testdir", -------- 修改权限命令,chmod 权限 目标 之间间隔有且仅有一个空格,权限必须为0xxxx格式 "chown 99 99 /testdir",-------- 修改属组命令,chown uid gid 目标 之间间隔有且仅有一个空格 "mkdir /testdir2", "mount vfat /dev/mmcblk0p0 /testdir2 noexec nosuid" -------- mount命令,格式为:mount 文件系统类型 source target flags data -------- flags当前仅支持nodev、noexec、nosuid和 rdonly,各项均以一个空格分开 ] }, { "name" : "init", -------- job名称当前仅支持识别“pre-init”、“init”和“post-init” "cmds" : [ -------- 单个job目前最多支持30条cmd "start service1", -------- 启动服务命令1 "start service2" -------- 启动服务命令2(可以根据需要调整命令在数组中的顺序,init进程将根据解析顺序依次执行) ] }, { "name" : "post-init", -------- 在init之后执行的 job,可以放置一些启动进程之后的操作 "cmds" : [] } ], "services" : [{ -------- service集合(数组形式),包含了init进程需要启动的所有系统服务(当前最多支持100个服务) "name" : "service1", -------- 当前服务的服务名,须确保非空且长度<=32字节 "path" : "/bin/process1" -------- 当前服务的可执行文件全路径,须确保非空且长度<=64字节 "uid" : 1, -------- 当前服务进程的uid值 "gid" : 1, -------- 当前服务进程的gid值 "once" : 0, -------- 当前服务进程是否为一次性进程 0 --- 当前服务非一次性进程,当进程因任何原因退出时,init收到SIGCHLD信号后将重新启动该服务进程 非0 --- 当前服务为一次性进程,当进程因任何原因退出时,init不会重新启动该服务进程 "importance" : 1, -------- 当前服务是否为关键系统进程 0 --- 当前服务非关键系统进程,当进程因任何原因退出时,init不会做系统复位操作 非0 --- 当前服务为关键系统进程,当进程因任何原因退出时,init收到SIGCHLD信号后进行系统复位重启 "caps" : [0, 1, 2, 5] -------- 当前服务所需的capability值,根据安全子系统已支持的capability,评估所需的capability,遵循最小权限原则配置(当前最多可配置100个值) }, { "name" : "service2", -------- 下一个需要init启动的服务。此处服务的顺序与启动顺序无关,启动顺序取决于上面job中的cmd顺序。 "path" : "/bin/process2", "uid" : 2, "gid" : 2, "once" : 1, "importance" : 0, "caps" : [ ] } ] } ``` **表 2** cmds支持列表

命令名称

命令格式

命令说明

start

start ServiceName 间隔有且仅有一个空格

启动服务,服务名称与文件中services数组中服务名称相同

mkdir

mkdir /xxxx/xxx 间隔有且仅有一个空格

创建目录

chmod

chmod 0xxx /xxx/xx 间隔有且仅有一个空格

修改权限,权限值必须为0xxx格式,如0755,0600等,需要遵循权限最小原则配置

chown

chown uid gid /xxx/xx 间隔有且仅有一个空格

修改属组

mount

mount fileSysType source target flags data

间隔有且仅有一个空格

挂载命令,其中flags目前仅支持nodev、noexec、nosuid和rdonly,其它字串均判定为data项

需要注意的是,init.cfg文件的修改需要保持json格式不被破坏,否则init进程解析失败后不会启动任何服务。对于配置的服务权限(uid/gid/capability)需要符合安全子系统要求且遵循权限最小原则。另外,对于once和importance项均为0的服务,若其在4分钟内连续退出次数超过4次,则init将终止重新启动该服务的操作。 - 系统参数 - OEM厂商相关系统属性 Hi3516DV300,Hi3518EV300开发板需要修改vendor/huawei/camera/hals/utils/sys\_param目录下源文件: ``` static const char HOS_PRODUCT_TYPE[] = {"****"}; static const char HOS_MANUFACTURE[] = {"****"}; static const char HOS_BRAND[] = {"****"}; static const char HOS_MARKET_NAME[] = {"****"}; static const char HOS_PRODUCT_SERIES[] = {"****"}; static const char HOS_PRODUCT_MODEL[] = {"****"}; static const char HOS_SOFTWARE_MODEL[] = {"****"}; static const char HOS_HARDWARE_MODEL[] = {"****"}; static const char HOS_HARDWARE_PROFILE[] = {"aout:true,display:true"}; static const char HOS_BOOTLOADER_VERSION[] = {"bootloader"}; static const char HOS_SECURE_PATCH_LEVEL[] = {"2020-6-5"}; static const char HOS_ABI_LIST[] = {"****"}; ``` Hi3861开发板需要修改vendor/huawei/wifi-iot/hals/utils/sys\_param目录下源文件: ``` static const char HOS_PRODUCT_TYPE[] = {"****"}; static const char HOS_MANUFACTURE[] = {"****"}; static const char HOS_BRAND[] = {"****"}; static const char HOS_MARKET_NAME[] = {"****"}; static const char HOS_PRODUCT_SERIES[] = {"****"}; static const char HOS_PRODUCT_MODEL[] = {"****"}; static const char HOS_SOFTWARE_MODEL[] = {"****"}; static const char HOS_HARDWARE_MODEL[] = {"****"}; static const char HOS_HARDWARE_PROFILE[] = {"aout:true,display:true"}; static const char HOS_BOOTLOADER_VERSION[] = {"bootloader"}; static const char HOS_SECURE_PATCH_LEVEL[] = {"2020-6-5"}; static const char HOS_ABI_LIST[] = {"****"}; ``` - 获取默认系统属性 ``` char* value1 = GetProductType(); printf("Product type =%s\n", value1); free(value1); char* value2 = GetManufacture(); printf("Manufacture =%s\n", value2); free(value2); char* value3 = GetBrand(); printf("GetBrand =%s\n", value3); free(value3); ``` - 设置获取自定义系统属性 ``` const char* defSysParam = "data of sys param ***..."; char key[] = "rw.parameter.key"; char value[] = "OEM-hisi-10.1.0"; int ret = SetParameter(key, value); char valueGet[128] = {0}; ret = GetParameter(key, defSysParam, valueGet, 128); printf("value = %s\n", valueGet); ``` ## 涉及仓 startup\_frameworks\_syspara\_lite startup\_hals\_syspara\_lite startup\_interfaces\_kits\_syspara\_lite startup\_appspawn\_lite startup\_services\_bootstrap\_lite startup\_init\_lite