1
技術背景
OpenHarmony release3.1版本在2.0的基礎之上不僅增加了功能,而且各模塊組件的能力也有所增強,本文就3.1版本的init啟動子系統模塊,在啟動引導系統服務方面進行分析。本文檔是基于碼云上release3.1分支代碼進行分析。
啟動子系統負責整個系統各個進程運行時環境的構建及進程引導,不同層級的進程有著不同的運行環境,運行環境決定著系統進程的設計。在增強啟動子系統能力方面有以下方面:
基礎能力增強:進程啟動、回收機制增強,維護命令統一以及插件化管理;
并行啟動:最大化并行啟動,為依賴資源提供同步機制,運行時進行資源獲取;
按需啟動:無訪問不啟動,減少常駐內存;
分組啟動:可對服務進行靈活組裝,提供整機不同的啟動級別能力。
2
Init啟動功能概述
1.基礎能力的增強
進程啟動,支持進程的selinux策略配置,擴展AccessToken設置,支持綁核配置;進程回收,支持進程頻繁退出抑制機制;維護命令,統一init的維護命令,包括系統參數和進程管理;插件化管理,init部件與周邊模塊關聯度高,通過插件化機制供其它模塊擴展。
2.進程分組&并行啟動
支持服務分組配置,如支持系統知名group,支持整機開機、重啟、關機、待機、充電等模式;支持服務依賴管理,支持并行啟動依賴同步機制。
3.按需啟動
支持SA類進程按需啟動,HDF類進程按需啟動,socket類進程的按需啟動;支持熱插拔事件驅動進程按需啟動;支持為按需啟動定時啟動、進程代持fd等輔助功能。
3
系統能力增強點分析
1.進程啟動能力增強
進程啟動時,支持在配置文件中配置服務進程的綁核、優先級、selinux策略加載以及AccessToken信息。
1)配置服務進程綁核能力
在服務的cfg配置文件中,配置綁核,例如param_watcher服務。系統啟動之后通過taskset -p pid,查看服務綁核情況,例如 current affinity mask: 3,即表示param_watcher服務運行在兩個cpu上切換。
“services” : [{“name” : “param_watcher”,…“cpucore” : [0,1]},
(左右移動查看全部內容)
通過CJSON解析 cfg 文件,獲取屬性”cpucore”屬性值的數組,然后通過接口CPU_SET設置進程的CPU.
在init,fork()服務子進程時設置CPU綁核。
2)配置服務進程優先級
在服務cfg文件中配置進程的優先級,例如appspawn.cfg中配置"importance" : -20,即設置appspawn的優先級為-20。
{ "services" : [{ "name" : "appspawn", "path" : ["/system/bin/appspawn"], "importance" : -20, "uid" : "root", "gid" : ["root"], "start-mode" : "boot" } ] }
代碼中通過CJSON解析cfg文件中”importance”屬性,得到服務的優先級,同時通過SetimportantValue回調函數保存優先級屬性。
在ServiceExec執行進程命令之前通過setpriority設置服務的優先級。
3)服務的selinux策略加載
OpenHarmony正在不斷完善selinux安全策略,后面對于服務的管控會更加嚴格。Init啟動在服務cfg文件中提供配置進程的Selinux接口,例如updater_sa.cfg文件中配置
“secon” : “uupdater_sa:s0”。 {“services” : [{“name” : “updater_sa”,“path” : [“/system/bin/sa_main”, “/system/profile/updater_sa.xml”],“uid” : “system”,“gid” : [“system”, “shell”],“secon” : “uupdater_sa:s0”}]}
通過JSON解析cfg文件中"secon"屬性,獲取服務的selinux值。
在init初始時,加載selinux LoadPolicy。
在init fork子進程時,通過SetSecon 設置服務的selinux。
4)配置服務進程AccessToken屬性
在服務cfg文件中配置進程的AccessToken,即cfg文件中配置“apl”: “xxx”,設置一串令牌。
通過JSON解析cfg文件中"apl"屬性,獲取服務的apl值。
在init fork 子進程的時候設置進程的AccessToken.
2.進程啟動&回收能力增強
1)進程的啟動流程
init啟動系統服務進程時都是先fork再execv執行目標服務進程而完成啟動。Fork的流程又細分為
pre-fork:即服務進程不需要真正的啟動,只是由init做好服務的準備工作,服務被訪問時拉起服務;
fork:只要fork成功,init就接著啟動下一個進程,即使后面execv執行失敗也忽略,最大承擔并行啟動服務;
execv:fork完成之后需要execv執行成功,才算服務啟動完成;
service:在服務啟動完成之后,通過setparameter 設置服務啟動標志"startup.service.ctl.serviceName" 為SERVICE_STARTED。
2)子進程退出資源回收
init監聽到任何子進程退出都需要waitpid回收該進程,避免出現僵尸進程。
3)設置服務啟動特殊模式
通過在服務的cfg文件中配置Once、DisabLED、Critical屬性值設置服務啟動的特殊方式。
Default:默認情況下服務退出之后,init會再次拉起服務;
Once:服務是單次啟動模式,退出之后init不再拉起;
Disabled:服務是被禁用的,退出后也不會拉起;
Critical:服務失敗后需要重新拉起,但是失敗N次之后,系統就會重啟,默認是4次。
常駐服務進程如果一直異常退出,為了避免頻繁嘗試拉起該服務,增加抑制機制,默認3秒內連續退出超過5次則不再自動拉起該服務。
核心服務進程如果一直異常退出,為了避免系統不可用,嘗試系統重啟;默認20秒內連續退出超過4次則不再自動拉起該服務。
例如 “critical” : [1, 1, 60], 代表有critical attribute,同時60秒內重啟1次,就系統重啟。通過GetCritical函數解析critical 屬性,通過CalculateCrashTime函數判斷是否需要重啟服務,或是reboot系統。
3.提供整機狀態服務
1)整機狀態
各系統服務進程啟動后,還需要相應整機提供的重啟、關機等請求(對應整機狀態變化能夠對進程進行相應處理stop、suspend、freeze等)。
重啟、shutdown關機:關閉服務進程,通過stop命令關閉服務;
Suspend關機:STR帶電低功耗關機,可快速開機,服務可選擇的退出或清理資源;
Freeze關機:STD系統快照寫到Disk,可完全掉電并快速開機。
通過reboot命令,設置 "startup.device.ctl"參數給外界提供當前整機的狀態,系統服務進程可通過ParameterClient的watch機制監聽整機的狀態變化,處理自己的狀態。
Reboot 命令:
2)服務可以通過start/stop來啟動停止
通過以下命令可以啟動或者停止服務。
start_service servicename --start servicestop_service servicename --stop serviceservice_control start servicename --start serviceservice_control stop servicename --stop service
最終通過SystemSetParameter(“ohos.ctl.start”, nameValue)啟動服務,其中nameValue是服務名+服務的參數組合數組。
4.按需啟動
1)SA進程按需啟動
需要按需啟動的SA服務,通過在cfg文件配置”dynamic” : true,設置此SA服務為按需啟動,即init在start service的時候解析到此屬性,不直接拉起服務;而是通過client端觸發samgr拉起服務。
動態加載系統服務進程及SystemAbility, 系統進程無需開機啟動,而是在SystemAbility被訪問的時候按需拉起,并加載指定SystemAbility。繼承SystemAbilityLoadCallbackStub類,并覆寫OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr& remoteObject)、OnLoadSystemAbilityFail(int32_t systemAbilityId)方法。
調用samgr提供的動態加載接口LoadSystemAbility(int32_t systemAbilityId, const sptr& callback)。
Samgr通過調用init提供的ServiceControlWithExtra接口,拉起服務。
3)socket進程按需啟動
init在pre-fork階段為socket類進程創建好socket,init中監聽創建好的socket上的網絡事件,socket上有報文事件后,init拉起socket進程進行報文處理。
socket進程無報文處理后,可以自動退出,退出后init回收該子進程并重新監聽socket網絡數據。
在服務cfg文件中添加”ondemand” : true 配置,設置socket服務為按需啟動。
在fork 子進程的時候,判斷服務是ondemand的,則創建socket監聽。
通過回調函數ProcessWatchEvent_處理socket按需啟動的事件。
4)熱插拔服務進程按需啟動
配置ueventd.cfg配置文件中設備節點屬性,例如,/dev/binder屬性配置為 ohos.dev.binder,當設備節點被創建好,param設置ohos.dev.binder屬性值為added。
在相應服務的cfg文件中,配置”job”為condition,如下:
“condition” : “ohos.dev.binder=added”
即當條件滿足時觸發服務拉起。
5)定時拉起&fd代持
定時拉起:服務進程在退出前可根據業務需要預約下次啟動的時間。
fd代持:按需啟動進程可以保持退出前的fd狀態句柄不丟失。按需啟動進程退出前可發fd發送給init代持,再次啟動后再獲取fd。
在服務的cfg配置"timer_start" : 6 ,設置服務6秒后拉起。通過LE_CreateTimer創建定時器,定時時間到達時,觸發回調函數,拉起服務。
創建fdhold的socket,注冊event loop回調函數ProcessFdHoldEvent監聽。
5.并行啟動及依賴管理
begetd啟動分三個階段,pre-init和init階段完成公共依賴部分;后續所有的服務都是并行化啟動。服務啟動的依賴包括Job和Service。
1)Job
所有的Job由init特權進程完成,可包括:設置全局環境變量,設置特權/proc, /sys節點參數等。
2)Service
Service依賴的前置條件可在啟動腳本里指定Job完成。例如在service 中配置
“service”:“jobs” : { “on-start” : “services:console” }“job”:{ “name” : “services:console”, “cmds” : [ “chmod 0773 /data/misc/trace”, “chmod 0775 /data/misc/wmtrace” ]}
即在fork子進程的時候執行job相關的命令。
通過cfg文件設置服務的”start-mode”來管理正常啟動還是并行啟動。
“start-mode” : “boot”“start-mode” : “normal”“start-mode” : “condition”
其中boot、normal 模式是并行啟動,service不寫start-mode默認也是normal。Condition模式必須通過 start service 來拉起。
Start-mode通過注冊鉤子函數,通過trigger拉起服務。
6.分組管理
系統服務可以按照分組進行管理,設備級知名group用于完成整機的開機、待機、充電等功能。默認的整機開機是放到GROUP_BOOT中,GROUP_CHARING是充電模式。
以charging group舉例說明。
配置device.charing.group.cfg 里面設置需要的jobs、services以及groups。
解析group 的cfg文件。
通過hash表保存group的配置。
通過cmdline獲取當前的group 模式,從而啟動進入不同的group,系統進入不同的模式。
4
總結
Release3.1 版本在OpenHarmony2.0的基礎上各方面能力都有所提升,性能和穩定性方面有所改善。Init組件中加入selinux配置,增強了系統的安全模式,按需啟動模式節約系統的內存資源,并行啟動增加了系統的啟動效率,分組啟動模式為后期系統進入不同狀態模式提供有效的接口。總之OpenHarmony在開源社區中,通過大家的共同努力正在茁長成長,總有一天會長成蒼天大樹,枝繁葉茂,造福人類。
審核編輯 :李倩
-
子系統
+關注
關注
0文章
109瀏覽量
12419 -
OpenHarmony
+關注
關注
25文章
3730瀏覽量
16424
原文標題:OpenHarmony release 3.1 版本啟動子系統功能分析
文章出處:【微信號:HarmonyOS_Community,微信公眾號:電子發燒友開源社區】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論