1# 系统参数 2## 概述 3### 功能简介 4 5OHOS系统参数为各系统服务提供简单易用的键值对访问接口,使得各个系统服务可以通过各自的系统参数来进行业务功能的配置。 6 7### 系统参数定义 8 9每个子系统定义各自模块的系统参数,包括系统参数名称、默认值以及系统参数的权限访问信息。 10#### 系统参数定义文件 11 12- 系统参数定义文件后缀名为".para" ,其格式示例如下: 13 14 ``` 15 const.product.name=OHOS-PRODUCT 16 const.os.version.api=26 17 const.telephony.enable=false|true 18 ``` 19#### 系统参数名(key)定义 20 21- 系统参数命名格式 22 23 系统参数名称采用点分格式,由多段组成,每一段可以由字母、数字、下划线组成,总长度不超过96字节;系统参数名称分为两类: 24 25 系统参数名称 26 27 | 类别 | 名称 | 示例 | 说明 | 28 | -------- | -------- | -------- | -------- | 29 | 参数名称 | Parameter Name | const.product.**name** | 完整的系统参数名称,末尾不是"."。 | 30 | 参数目录 | Parameter Directory | const.**. | 以"."结尾,标识相同前缀的所有系统参数集合。 | 31 32- 系统参数类型 33 34 系统参数一共分为三大类: 35 36 系统参数分类 37 38 | 类别 | 前缀 | 说明 | 39 | -------- | -------- | -------- | 40 | 常量 | const. | 常量参数,一旦赋值后续不会再变更;值最大长度为4096字节(包括结束符)。 | 41 | 可写 | 其它 | 可写参数,重启后丢失,值最大长度96字节(包括结束符)。| 42 | 可持久化 | persist. | 可写并可持久化保存参数,重启后不会丢失,值最大长度96字节(包括结束符)。| 43 44 每个系统参数名称总体格式如下: 45 46 ```java 47 [ const | persist ].$sub_system.$desc 48 ``` 49 $sub_system为子系统或模块的名称。 50 51 $desc为子系统或模块下参数的描述字符,可以为点分格式进行分级描述。 52 53#### 系统参数值(value)定义 54 55- 系统参数的赋值分为三大类: 56 57系统参数赋值方式 58 59| 类别 | 示例 | 说明 | 60| -------- | -------- | -------- | 61| 字符串 | const.product.name=OHOS-PRODUCT | 多行字符串需要通过引号扩起来。 | 62| 数字 | const.os.version.api=26 | 数字不需要。| 63| 布尔 | const.telephony.enable=false | 布尔型的可以为0,1,false,true。| 64 65### 系统参数权限设置 66 67系统参数支持DAC和MAC访问控制。 68#### 默认权限 69 70系统参数没有定义任何DAC,MAC权限时,其默认权限为: 71 72| [DAC] User | [DAC] Group | [DAC] UGO | [MAC] SELinux Label | 73| ---------- | ----------- | --------- | ------------------- | 74| root | root | 775 | default_param | 75 76Other进程对默认权限参数的访问行为列举如下: 77 78| 操作 | 系统Native进程 | 系统应用进程 | 三方应用进程 | 79| ----- | -------------- | ------------ | ------------ | 80| get | 允许 | 允许 | 允许 | 81| watch | 允许 | 允许 | 允许 | 82| set | 不允许 | 不允许 | 不允许 | 83 84#### DAC访问控制权限设置 85 86- 系统参数DAC访问控制定义文件 87 88 当前系统参数的访问权限控制通过自主访问控制(Discretionary Access Control)方式管理,访问权限定义文件后缀名为".para.dac" ,init下的文件路径为/base/startup/init/services/etc/param/ohos.para.dac,具体定义内容示例如下: 89 90 ``` 91 const.product. = root:root:0775 92 persist.init. = root:root:0775 93 startup.appspawn. = root:root:0750 94 startup.uevent. = ueventd:ueventd:0775 95 ``` 96 97 如上所示,可以为相同前缀的所有系统参数定义一类访问权限信息,DAC信息通过":"分三段来描述,分别为参数的user,group以及UGO规则信息。 98 99 UGO规则信息每一位的定义如下: 100 101 **图1** UGO规则信息 102 103  104 105#### MAC访问控制权限设置 106 107 - 添加selinux标签 108 109 为系统参数添加selinux标签,首先需要在文件/base/security/selinux_adapter/sepolicy/base/public/parameter.te中定义标签,例如: 110 111 ```java 112 type servicectrl_param, parameter_attr 113 ``` 114 115 标签定义完成后,在文件/base/security/selinux_adapter/sepolicy/base/public/parameter_contexts中添加和标签关联的系统参数前缀,这里以前缀ohos.servicectrl.为例: 116 117 ```java 118 ohos.servicectrl. u:object_r:servicectrl_param:s0 119 ``` 120 121 - 给init授权,允许map等操作,在文件/base/security/selinux/sepolicy/ohos_policy/startup/init/public/init.te中补充下面内容: 122 123 ```java 124 allow servicectrl_param tmpfs:filesystem associate; 125 allow init servicectrl_param:file { map open read relabelto relabelfrom }; 126 ``` 127 128 - 设置写权限,这里允许init samgr hdf_devmgr 进行系统参数写: 129 130 ```java 131 allow { init samgr hdf_devmgr } servicectrl_param:parameter_service { set }; 132 ``` 133 134 - 设置读权限,如果只允许部分进程访问可单独对该进程授权: 135 136 ```java 137 allow { xxx } servicectrl_param:file { map open read }; 138 ``` 139 140 - 如果全部允许,则设置为: 141 142 ```java 143 allow { domain -limit_domain } servicectrl_param:file { map open read }; 144 ``` 145 146#### 系统参数权限基本要求 147 148 每个selinux标签对应的系统参数有独立的共享内存区,同类型的系统参数建议共用selinux标签,减少系统共享内存的开销。 149 150 以sample部件为例,建议增加以下几类标签进行访问控制: 151 152 a)公开只读的系统参数,不需要定义新的标签,使用default_param 153 154 b)可写系统参数:增加标签{component}_writable_param 155 156 c)仅部件内部可读的系统参数(隐私数据):增加标签【可选】 {component}_private_param 157 158### 系统参数标签配置 159 160#### 系统参数标签文件大小配置 161 162每个标签默认分配1K内存,能存放5个左右的系统参数。如果标签下支持的系统参数较多,需在ohso.para.size文件中按照标签扩大内存大小。 163 164支持/system/etc/param/ohos.para.size和/sys_prod/etc/param/ohos.para.size进行扩展。 165 166配置规则: 167 168系统参数标签=大小 169 170例如: 171 172``` 173devinfo_public_param=30720 174hilog_param=40960 175``` 176 177默认系统参数的共享内存大小:80KB 178 179#### 系统参数标签说明 180 181 init 会根据系统参数标签在/dev/__parameters__/目录下创建对应的共享内存映射文件,该共享内存用来存储与该标签绑定的系统参数。 182 183 共享内存文件示例: 184 185 ``` 186 -rwxr-xr-- 1 root root 30720 2017-08-10 16:22 u:object_r:default_param:s0 187 -rwxr-xr-- 1 root root 1024 2017-08-10 16:22 u:object_r:devinfo_private_param:s0 188 -rwxr-xr-- 1 root root 30720 2017-08-10 16:22 u:object_r:devinfo_public_param:s0 189 -rwxr-xr-- 1 root root 40960 2017-08-10 16:22 u:object_r:hilog_param:s0 190 ``` 191 192 系统参数标签会在/base/security/selinux_adapter/sepolicy/base/public/parameter.te文件中定义: 193 194 系统参数标签定义: 195 196 ``` 197 type default_param, parameter_attr; 198 type devinfo_private_param, parameter_attr; 199 type devinfo_public_param, parameter_attr; 200 type hilog_param, parameter_attr; 201 ``` 202 203 系统参数标签与系统参数的关联在/base/security/selinux_adapter/sepolicy/base/public/parameter_contexts定义: 204 205 以hilog_param标签为例: 206 207 ``` 208 hilog. u:object_r:hilog_param:s0 #以hilog.为前缀的系统参数存储在hilog_param标签对应的共享内存中 209 persist.sys.hilog. u:object_r:hilog_param:s0 #以persist.sys.hilog.为前缀的系统参数也存储在hilog_param标签对应的共享内存中 210 ``` 211### 查看系统参数共享内存占用情况 212 213 系统参数共享内存占用情况的查询,提供了查询命令:param dump [verbose] 214 215 查询结果的介绍说明如下: 216 217 ``` 218 Dump all parameters begin ... 219 Local security information 220 pid: 1612 uid: 0 gid: 0 221 map file: u:object_r:default_param:s0 // 系统参数标签名称(共享内存映射文件名) 222 total size: 10485720 // 系统参数标签文件大小(标签映射的共享内存大小) 223 first offset: 0 // 第一个参数节点的偏移量 224 current offset: 15948 // 当前的参数节点的偏移量 225 total node: 242 // 该标签内节点总数 226 total param node: 219 // 参数节点总数 227 total security node: 0 // selinux节点数 228 commitId : 26 // 229 commitPersistId : 0 // 230 node info: // 该标签下所有节点的信息 231 ... ... 232 ``` 233### 系统参数的加载顺序 234 235 系统参数加载顺序 236 237 | 类别 | 路径 | 说明 | 238 | -------- | -------- | -------- | 239 | 内核参数 | /proc/cmdline | 将内核参数中的部分值转化成系统参数,并保存。内核参数中.xxx=valXXX类型的参数都转换成ohos.boot.xxx=valXXX系统参数。 | 240 | OS系统参数 | /system/etc/param/ohos_const/*.para | OS固定系统参数值参数优先加载。 | 241 | vendor参数 | /vendor/etc/param/*.para | 厂商定义的系统参数次优先级加载。 | 242 | system参数 | /system/etc/param/*.para | 加载各子系统定义的参数参数。如果系统参数已经存在,则忽略掉。 | 243 | persist参数 | /data/parameters/ | 如果持久化参数存在,则最后加载持久化系统参数。持久化系统参数会覆盖加载的默认系统参数。 | 244 245### 参数和标签的展示 246 247 目前按照子系统,部件把参数和标签统计的信息已经录入数据库,可以搭建[OpenHarmony实时架构信息收集与分析系统](https://gitee.com/handyohos/ohos_archinfo/tree/master)进行查看 248 249 搭建服务可参考:[OpenHarmony实时架构信息analyser模块说明](https://gitee.com/handyohos/ohos_archinfo/blob/master/analyser/README.md) 250 251 自行收集数据库信息可参考:[OpenHarmony实时架构信息收集与分析系统](https://gitee.com/handyohos/ohos_archinfo/tree/master#/handyohos/ohos_archinfo/blob/master/collector/README.md) 252 253 数据库也可以取每日构建的dayu200-db 254### 系统参数的基本操作 255 256系统参数操作原语 257 258 259 260系统参数操作原语说明 261| 功能 | 说明 | 262| -------- | -------- | 263| get | 获取系统参数的值 | 264| set | 设置系统参数的值 | 265| wait | 同步等待系统参数的值变更 | 266| watch | 异步观察系统参数的值变更 | 267 268### 约束与限制 269 270仅限小型系统、标准系统下使用。 271 272## 开发指导 273 274### 场景介绍 275设定特定的系统参数 276 277### 接口说明 278 279 - Shell命令接口 280 281 通过shell命令中可直接操作系统参数(只在标准系统提供)。系统参数shell命令如下表所示: 282 283 **表6** 系统参数shell命令说明 284 285 | 功能 | 说明 | 286 | -------- | -------- | 287 | param get [**key**] | 获取指定key名称的系统参数值;如果不指定任何name,则返回所有系统参数值。 | 288 | param set **key value** | 设置指定key名称的参数值为value。 | 289 | param wait **key** **value** | 同步等待指定key名称的系统参数值与value匹配。value可支持模糊匹配,如"*"表示任何值,"val\*"表示只匹配前三个val字符。 | 290 291 - syspara系统接口 292 293 在Coding中可以调用下列函数接口,获取对应的系统参数值(系统参数接口返回的为const字符串,不支持free操作)。 294 295 **表7** 系统属性接口说明 296 | 接口名 | 描述 | 297 | -------- | -------- | 298 | int GetParameter(const char\* key, const char\* def, char\* value, unsigned int len) | 获取系统参数。 | 299 | int SetParameter(const char\* key, const char\* value) | 设置/更新系统参数。 | 300 | const char\* GetDeviceType(void) | 返回当前设备类型。 | 301 | const char\* GetManufacture(void) | 返回当前设备生产厂家信息。 | 302 | const char\* GetBrand(void) | 返回当前设备品牌信息。 | 303 | const char\* GetMarketName(void) | 返回当前设备传播名。 | 304 | const char\* GetProductSeries(void) | 返回当前设备产品系列名。 | 305 | const char\* GetProductModel(void) | 返回当前设备认证型号。 | 306 | const char\* GetSoftwareModel(void) | 返回当前设备内部软件子型号。 | 307 | const char\* GetHardwareModel(void) | 返回当前设备硬件版本号。 | 308 | const char\* GetHardwareProfile(void) | 返回当前设备硬件profile。 | 309 | const char\* GetSerial(void) | 返回当前设备序列号(SN号)。 | 310 | const char\* GetOSFullName(void) | 返回操作系统名。 | 311 | const char\* GetDisplayVersion(void) | 返回当前设备用户可见的软件版本号。 | 312 | const char\* GetBootloaderVersion(void) | 返回当前设备Bootloader版本号。 | 313 | const char\* GetSecurityPatchTag(void) | 返回安全补丁标签。 | 314 | const char\* GetAbiList(void) | 返回当前设备支持的指令集(Abi)列表。 | 315 | int GetSdkApiVersion(void) | 返回与当前系统软件匹配的SDK API 版本号。 | 316 | int GetFirstApiVersion(void) | 返回系统软件首版本SDK API 版本号。 | 317 | const char\* GetIncrementalVersion(void) | 返回差异版本号。 | 318 | const char\* GetVersionId(void) | 返回版本id。 | 319 | const char\* GetBuildType(void) | 返回构建类型。 | 320 | const char\* GetBuildUser(void) | 返回构建账户用户名。 | 321 | const char\* GetBuildHost(void) | 返回构建主机名。 | 322 | const char\* GetBuildTime(void) | 返回构建时间。 | 323 | const char\* GetBuildRootHash(void) | 返回当前版本hash。 | 324 | const char\* GetOsReleaseType(void) | 返回系统发布类型。 | 325 | int GetDevUdid(char \*udid, int size) | 获取设备udid。 | 326 | const char *AclGetSerial(void); | 返回当前设备序列号(SN号)(带访问权限检查)。 | 327 | int AclGetDevUdid(char *udid, int size); | 获取设备udid(带访问权限检查)。 | 328 329### 开发步骤 330 3311. 系统参数定义 332 333 通过定义子系统或者产品的.para和.para.dac文件,实现默认系统参数的定义和权限控制。 334 335 在标准系统上通过ohos_prebuilt_para模版安装配置文件到到/etc/param/目录下,GN脚本示例如下: 336 337 ```go 338 import("//base/startup/init/services/etc/param/param_fixer.gni") 339 340 ohos_prebuilt_para("ohos.para") { 341 source = "//base/startup/init/services/etc/ohos.para" 342 part_name = "init" 343 module_install_dir = "etc/param" 344 } 345 346 ohos_prebuilt_para("ohos.para.dac") { 347 source = "//base/startup/init/services/etc/ohos.para.dac" 348 part_name = "init" 349 module_install_dir = "etc/param" 350 } 351 ``` 352 353 在小系统上,通过copy命令,把对应的系统参数定义文件拷贝到system/etc/param目录下 354 ```go 355 copy("ohos.para") { 356 sources = [ "//base/startup/init/services/etc/param/ohos.para" ] 357 outputs = [ "$root_out_dir/system/etc/param/ohos.para" ] 358 } 359 copy("ohos.para.dac") { 360 sources = [ "//base/startup/init/services/etc/param/ohos.para.dac" ] 361 outputs = [ "$root_out_dir/system/etc/param/ohos.para.dac" ] 362 } 363 ``` 364 在mini系统上,通过action把所有定义的默认系统参数转化成头文件,并编译到系统中 365 ```go 366 action("lite_const_param_to") { 367 script = "//base/startup/init/scripts/param_cfg_to_code.py" 368 args = [ 369 "--source", 370 rebase_path( 371 "//base/startup/init/services/etc_lite/param/ohos_const/ohospara"), 372 "--dest_dir", 373 rebase_path("$root_out_dir/gen/init/"), 374 "--priority", 375 "0", 376 ] 377 outputs = [ "$target_gen_dir/${target_name}_param_cfg_to_code.log" ] 378 } 379 ``` 3802. 系统参数使用实例 381 ``` 382 // set && get 383 char key1[] = "rw.sys.version"; 384 char value1[] = "10.1.0"; 385 int ret = SetParameter(key1, value1); 386 char valueGet1[128] = {0}; 387 ret = GetParameter(key1, "version=10.1.0", valueGet1, 128); 388 389 // get sysparm 390 char* value1 = GetDeviceType(); 391 printf("Product type =%s\n", value1); 392 393 char* value2 = GetManufacture(); 394 printf("Manufacture =%s\n", value2); 395 396 char* value3 = GetBrand(); 397 printf("GetBrand =%s\n", value3); 398 399 char* value4 = GetMarketName(); 400 printf("MarketName =%s\n", value4); 401 402 char* value5 = GetProductSeries(); 403 printf("ProductSeries =%s\n", value5); 404 405 char* value6 = GetProductModel(); 406 printf("ProductModel =%s\n", value6); 407 408 char* value7 = GetSoftwareModel(); 409 printf("SoftwareModel =%s\n", value7); 410 411 char* value8 = GetHardwareModel(); 412 printf("HardwareModel =%s\n", value8); 413 414 char* value9 = GetHardwareProfile(); 415 printf("Software profile =%s\n", value9); 416 417 char* value10 = GetSerial(); 418 printf("Serial =%s\n", value10); 419 420 char* value11 = GetOSFullName(); 421 printf("OS name =%s\n", value11); 422 423 char* value12 = GetDisplayVersion(); 424 printf("Display version =%s\n", value12); 425 426 char* value13 = GetBootloaderVersion(); 427 printf("bootloader version =%s\n", value13); 428 429 char* value14 = GetSecurityPatchTag(); 430 printf("secure patch level =%s\n", value14); 431 432 char* value15 = GetAbiList(); 433 printf("abi list =%s\n", value15); 434 435 int value16 = GetFirstApiVersion(); 436 printf("first api level =%d\n", value16); 437 438 char* value17 = GetIncrementalVersion(); 439 printf("Incremental version = %s\n", value17); 440 441 char* value18 = GetVersionId(); 442 printf("formal id =%s\n", value18); 443 444 char* value19 = GetBuildType(); 445 printf("build type =%s\n", value19); 446 447 char* value20 = GetBuildUser(); 448 printf("build user =%s\n", value20); 449 450 char* value21 = GetBuildHost(); 451 printf("Build host = %s\n", value21); 452 453 char* value22 = GetBuildTime(); 454 printf("build time =%s\n", value22); 455 456 char* value23 = GetBuildRootHash(); 457 printf("build root later..., %s\n", value23); 458 459 char* value24 = GetOsReleaseType(); 460 printf("OS release type =%s\n", value24); 461 462 char* value25 = GetOsReleaseType(); 463 printf("OS release type =%s\n", value25); 464 465 char value26[65] = {0}; 466 GetDevUdid(value26, 65); 467 printf("device udid =%s\n", value26); 468 ``` 469### 系统参数错误码说明 470 471**错误码说明** 472 473| 枚举 | 枚举值 | 说明 | 474| -------------------------------- | ------ | ----------------------------------------- | 475| PARAM_CODE_ERROR | -1 | 系统错误 | 476| PARAM_CODE_SUCCESS | 0 | 成功 | 477| PARAM_CODE_INVALID_PARAM | 100 | 系统参数接口的入参为空 | 478| PARAM_CODE_INVALID_NAME | 101 | 系统参数key不符合规范,长度或非法字符 | 479| PARAM_CODE_INVALID_VALUE | 102 | 系统参数value值不符合规范,长度或非法字符 | 480| PARAM_CODE_REACHED_MAX | 103 | 树节点已达最大值 | 481| PARAM_CODE_NOT_SUPPORT | 104 | 不支持此接口 | 482| PARAM_CODE_TIMEOUT | 105 | 访问服务端超时 | 483| PARAM_CODE_NOT_FOUND | 106 | 没有找到该参数 | 484| PARAM_CODE_READ_ONLY | 107 | 系统参数为只读参数 | 485| PARAM_CODE_IPC_ERROR | 108 | IPC通信异常 | 486| PARAM_CODE_NODE_EXIST | 109 | 系统参数的节点存在 | 487| PARAM_WATCHER_CALLBACK_EXIST | 110 | watcher的callback重复添加 | 488| PARAM_WATCHER_GET_SERVICE_FAILED | 111 | watcher获取服务失败 | 489| PARAM_CODE_MEMORY_MAP_FAILED | 112 | 建立文件共享内存映射失败 | 490| PARAM_WORKSPACE_NOT_INIT | 113 | workspace 没有初始化 | 491| PARAM_CODE_FAIL_CONNECT | 114 | 连接paramServer 失败 | 492| PARAM_CODE_MEMORY_NOT_ENOUGH | 115 | 系统参数空间不足 | 493| DAC_RESULT_INVALID_PARAM | 1000 | 无用,定义权限错误的起始值 | 494| DAC_RESULT_FORBIDED | 1001 | DAC权限被禁止 | 495| SELINUX_RESULT_FORBIDED | 1002 | selinux权限被禁止 | 496| PARAM_CODE_MAX | 1003 | 枚举最大值 | 497 498**错误定位关键日志** 499 500- system parameter set: 501 502 SetParameter failed! the errNum is: xx! 503 504 SystemSetParameter failed! name is : xxx, errNum is: xx! 505 506- system parameter get: 507 508 GetParameter_ failed! the errNum is: xx! 509 510 SystemReadParam failed! name is: xxxx, errNum is: xx! 511 512- system parameter wait: 513 514 WaitParameter failed! the errNum is: xx! 515 516 SystemWaitParameter failed! name is: xxx, errNum is: xx! 517 518- system parameter Watcher: 519 520 WatchParameter failed! the errNum is xx! 521 522 SystemWatchParameter is failed! keyPrefix is:xxx, errNum is:xx! 523## 系统参数常见问题 524 525### 如何设置一个系统参数 526 527 1、hdc shell进入终端,执行param set param.key.xxx(系统参数名) param.value.xxx(系统参数名值), 确认参数是否可以设置成功,成功则无需其他设置 528 529 2、代码侧设置系统参数,调用SetParameter接口,具体参照[接口说明](#接口说明) 530 531 3、执行param set 失败,则根据失败的日志确定对应的排查操作: 532 533 若dac 权限不足,参照DAC访问控制权限设置进行设置 534 535 若selinux 权限不足,根据" avc: denied" 告警信息设置对应规则 536 537 若内存不够,参照[系统参数标签配置](#系统参数标签配置)进行扩展 538 539### 如何读取一个系统参数 540 541 1、hdc shell进入终端,执行param get param.key.xxx(系统参数名), 查看参数是否可以读取成功,读取成功则无需其他操作 542 543 2、代码侧获取系统参数,调用GetParameter接口,具体参照[接口说明](#接口说明) 544 545 3、执行param get 失败,则根据失败的日志确定对应的排查操作: 546 547 首先需要确认该参数是否被设置,若没有被设置,则需要先设置该参数;若已设置,则进行下一步排查 548 549 若dac 权限不足,参照DAC访问控制权限设置进行设置 550 551 若selinux 权限不足,根据" avc: denied" 告警信息设置对应规则 552 553### 如何订阅一个系统参数的变化 554 555 1、hdc shell进入终端,执行param shell,进入Parameter shell后执行 watcher parameter param.key.xxx(系统参数名),当系统参数值发生变化时,会收到类似"Receive parameter commit 691 change aaa.aaa 11111"的消息 556 557 2、代码侧监控系统参数变化,调用WatchParameter接口 558 559 3、执行watcher parameter 失败,则根据失败的日志确定对应的排查操作: 560 561 若dac 权限不足,参照DAC访问控制权限设置进行设置 562 563 若selinux 权限不足,根据" avc: denied" 告警信息设置对应规则 564 565### 三方应用为何无法访问系统参数 566 567默认DAC规则只允许三方应用对参数具有get, watch 的权限,因此三方应用若需要set权限需要重新设置DAC规则。 此外, 三方应用的selinux权限默认是未设置的,因此需要参照mac访问控制权限设置进行设置 568