自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Hi3861_WiFi IoT工程:理解啟動恢復(fù)子系統(tǒng)

系統(tǒng)
文章由鴻蒙社區(qū)產(chǎn)出,想要了解更多內(nèi)容請前往:51CTO和華為官方戰(zhàn)略合作共建的鴻蒙技術(shù)社區(qū)https://harmonyos.51cto.com

[[396833]]

想了解更多內(nèi)容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)

https://harmonyos.51cto.com

Hi3861_WiFiIoT工程的一點理解

目錄

  • 1.關(guān)于工程本身
  • 2.ohos_bundles
  • 3.工程的目錄結(jié)構(gòu)
  • 4.理解IoT外設(shè)控制模塊
  • 4.1 BUILD.gn 的展開
  • 4.2 led_example.c 的展開
  • 4.3 IoT外設(shè)控制模塊的整體理解
  • 5.理解啟動恢復(fù)子系統(tǒng)
  • 5.1 #A分析SYS_INIT(service)
  • 5.2 #B分析MODULE_INIT(run)
  • 5.3 #C分析SAMGR_Bootstrap()
  • X.總結(jié):

更新記錄:

  • 說明:本文是 "Hi3861_WiFi IoT工程的一點理解" 的新增章節(jié),版本升級到v1.6.
  • 前面章節(jié)見:
  • Hi3861_WiFi IoT工程的一點理解v1.0
  • Hi3861_WiFi IoT工程:理解IoT外設(shè)控制模塊

5.理解啟動恢復(fù)子系統(tǒng)

這是一個非常重要的子系統(tǒng),我在之前《鴻蒙系統(tǒng)的啟動流程》一文中做過一些簡單的分析,建議先去看一下《鴻蒙系統(tǒng)的啟動流程v3.0》Part 1/2的3/4章節(jié)。這里就先到鴻蒙系統(tǒng)來整體看一下它具體是怎么回事,然后再回到本工程來對比看hpm的裁剪給我們留下了什么。

仍然是先看官方readme 和重新整理目錄結(jié)構(gòu)。

  1. 啟動恢復(fù)子系統(tǒng)負責(zé)從內(nèi)核啟動之后到應(yīng)用啟動之前的系統(tǒng)關(guān)鍵服務(wù)進程的啟動過程以及設(shè)備恢復(fù)出廠設(shè)置的功能。涉及以下組件: 
  2.  
  3. init啟動引導(dǎo)組件 
  4. init啟動引導(dǎo)組件對應(yīng)的進程為init進程,是內(nèi)核完成初始化后啟動的第一個用戶態(tài)進程。init進程啟動之后,讀取init.cfg配置文 件,根據(jù)解析結(jié)果,執(zhí)行相應(yīng)命令并依次啟動各關(guān)鍵系統(tǒng)服務(wù)進程,在啟動系統(tǒng)服務(wù)進程的同時設(shè)置其對應(yīng)權(quán)限。 
  5.  
  6. appspawn應(yīng)用孵化組件 
  7. 負責(zé)接收用戶程序框架的命令孵化應(yīng)用進程,設(shè)置新進程的權(quán)限,并調(diào)用應(yīng)用程序框架的入口函數(shù)。 
  8.  
  9. bootstrap服務(wù)啟動組件 
  10. 提供了各服務(wù)和功能的啟動入口標識。在SAMGR啟動時,會調(diào)用boostrap標識的入口函數(shù),并啟動系統(tǒng)服務(wù)。 
  11.  
  12. syspara系統(tǒng)屬性組件 
  13. 系統(tǒng)屬性組件,根據(jù)HarmonyOS產(chǎn)品兼容性規(guī)范提供獲取設(shè)備信息的接口,如:產(chǎn)品名、品牌名、廠家名等,同時提供設(shè)置/讀 取系統(tǒng)屬性的接口。 
  14.  
  15. startup啟動組件 
  16. 負責(zé)提供大型系統(tǒng)(參考內(nèi)存≥1GB)獲取與設(shè)置操作系統(tǒng)相關(guān)的系統(tǒng)屬性。 
  17.  
  18. 大型系統(tǒng)支持的系統(tǒng)屬性包括:設(shè)備信息如設(shè)備類型、產(chǎn)品名稱等,系統(tǒng)信息如系統(tǒng)版本、API版本等默認系統(tǒng)屬性。 

兩相比較就可以看到Hi3861工程相對于完整系統(tǒng)裁剪掉了appspawn_lite 和 init_lite兩個組件(先灰化掉了),因為啟動方式/流程上有比較大的差別,裁掉init_lite其實很容易理解,但為什么裁掉appspawn_lite我還沒仔細研究。

這里就只分析Hi3861的bootstrap_lite,至于syspara_lite比較簡單,看官方文檔照著上表右邊的調(diào)用順序就可以獲取屬性信息了。appspawn_lite 和 init_lite兩個組件,待我把相關(guān)細節(jié)搞清楚了,再完善到《鴻蒙系統(tǒng)的啟動流程》的更新版本中,或者單獨寫一個理解總結(jié)出來。

下面的文字,其實也算是《鴻蒙系統(tǒng)的啟動流程v3.0》Part 2的“4.第四階段:鴻蒙系統(tǒng)框架層的啟動”的完整分析版本。

官方readme 對bootstrap服務(wù)啟動組件的描述就兩句話,該怎么理解:

“提供了各服務(wù)和功能的啟動入口標識。” 就是指在//base/startup/services/bootstrap_lite/source/core_main.h 頭文件中定義的宏:SYS_INIT(name)和MODULE_INIT(name)。

“在SAMGR啟動時,會調(diào)用boostrap標識的入口函數(shù),并啟動系統(tǒng)服務(wù)。”就是指在system_init.c文件中的HOS_SystemInit()函數(shù)調(diào)用 SAMGR_Bootstrap(); 去啟動系統(tǒng)服務(wù)了。什么是“boostrap標識的入口函數(shù)”,我們在下面會解釋。

  1. void HOS_SystemInit(void) 
  2.  
  3.  
  4.     MODULE_INIT(bsp);       
  5.  
  6.     MODULE_INIT(device); 
  7.  
  8.     MODULE_INIT(core); 
  9.  
  10.     SYS_INIT(service);     //#A 
  11.  
  12.     SYS_INIT(feature); 
  13.  
  14.     MODULE_INIT(run);   //#B 
  15.  
  16.     SAMGR_Bootstrap();   //#C 
  17.  

灰掉部分目前我還未涉足,先跳過,但要是理解了下面的內(nèi)容,灰掉部分也就基本上理解了。

5.1 #A分析SYS_INIT(service)

打開//base/startup/services/bootstrap_lite/source/core_main.h 文件,工程編譯是使用gcc編譯器的,所以__GNUC__是有定義的。

把service代進去展開一下:

  1. #define SYS_INIT(service)     \ 
  2.     do {                   \ 
  3.         SYS_CALL(service, 0); \ 
  4.     } while (0) 
  5.  
  6. #define SYS_CALL(service, 0)                              \ 
  7.     do {                                              \ 
  8.         InitCall *initcall = (InitCall *)(SYS_BEGIN(service, 0));   \ 
  9.         InitCall *initend = (InitCall *)(SYS_END(service, 0));    \ 
  10.         for (; initcall < initend; initcall++) {                  \ 
  11.             (*initcall)();                                \ 
  12.         }                                            \ 
  13.     } while (0) 

SYS_BEGIN和SYS_END就不展開了,重點在for循環(huán),可能還是不太好理解,我再把它翻譯成大白話:

  1. for循環(huán)就是從 initcall 地址開始,到 initend地址(不含)結(jié)束, 
  2.  
  3. 依次調(diào)用*initcall內(nèi)的地址所指向的函數(shù),執(zhí)行函數(shù)內(nèi)的指令。 
  4.  
  5. initcall 是一個指針,其內(nèi)容 *initcall是符號__zinitcall_sys_service_start的地址,即 &__zinitcall_sys_service_start, 
  6.  
  7. initend 是一個指針,其內(nèi)容 *initend 是符號__zinitcall_sys_service_end的地址,即 &__zinitcall_sys_service_end 

Hi3516/Hi3518平臺工程,打開 build\lite\platform\......\link.ld

Hi3861工程則是 vendor\hisi\hi3861\hi3861\build\link\link.ld.S

可以看到上面的 start/end 符號,但估計你打開文件,看到里面的東西,心里還是會有很大的問號。

那就直接去看編譯后輸出的map文件:out\wifiiot\Hi3861_wifiiot_app.map,文本編輯器打開該文件,搜索一下:

這里有三個service 要 init,從抓回來的log看,確實如此:

這下應(yīng)該夠清楚了吧?

SYS_INIT(service) 是調(diào)用端的宏,對應(yīng)的,定義端也有一個對應(yīng)的宏SYS_SERVICE_INIT(xxx)。

工程代碼全局搜索一下“SYS_SERVICE_INIT”,把沒什么用的 sample和 .h中的先去掉,就得到四個:

前三個就是上面的三個service。

第四個“SYS_SERVICE_INIT(InitializeRegistry);”在

foundation\distributedschedule\services\samgr_lite\samgr_server\source\samgr_server.c 文件中,

看它的 BUILD.gn 文件“shared_library("server")”,再到上級目錄查看BUILD.gn,

  1. if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux"){ 
  2.     features += [ 
  3.         "samgr_server:server"
  4.         "samgr_client:client"
  5.     ] 

這是LiteOS_A或Linux內(nèi)核的平臺才會有的,所以Hi3861平臺的log上看不到這個server的log。

上面的三個service使用的宏SYS_SERVICE_INIT(Init),我們也一步一步展開,

  1. #define SYS_SERVICE_INIT(func)  LAYER_INITCALL_DEF(func, sys_service, "sys.service"
  2. #define LAYER_INITCALL_DEF(func, layer, clayer) \ 
  3.     LAYER_INITCALL(func, layer, clayer, 2)         //默認優(yōu)先級 2 
  4. #define LAYER_INITCALL(func, layer, clayer, priority)            \ 
  5.     static const InitCall USED_ATTR __zinitcall_##layer##_##func \ 
  6.         __attribute__((section(".zinitcall." clayer #priority ".init"))) = func 

__attribute__((section(“section_name”))) 其作用是將函數(shù)或數(shù)據(jù)放入指定名為"section_name"對應(yīng)的段中。

最后分別得到:

  1. //.zinitcall.sys.service2.init = Init  //bootstrap_service 的Init 
  2.  
  3. //.zinitcall.sys.service2.init = Init  //broadcast_service 的Init 
  4.  
  5. //.zinitcall.sys.service2.init = Init  //hiview_service 的Init 

編譯器根據(jù)attribute+section關(guān)鍵字,就把三個Init函數(shù)全都編譯鏈接到了 .zinitcall.sys.service2.init 對應(yīng)的段中,

結(jié)果就是上面Hi3861_wifiiot_app.map文件截圖的樣子。

5.2 #B分析MODULE_INIT(run)

對于MODULE_INIT(Xxx) 和對應(yīng)的SYS_RUN(Xxx)的分析,和上面沒什么差別,只是編譯鏈接的時候,將函數(shù)放到不同的段中去而已。

我在應(yīng)用層放了兩個APP,分別是helloworld和led_example,log中也看到對應(yīng)的log了。

5.3 #C分析SAMGR_Bootstrap()

SAMGER:system ability manager。系統(tǒng)服務(wù)框架子系統(tǒng),這是一個非常核心的子系統(tǒng)了,我會另開一章來分析。不過這里還是先簡單了解一下它在這一步,做了些什么事情。

先看官方文檔:

由于平臺資源有限,且硬件平臺多樣,因此需要屏蔽不同硬件架構(gòu)和平臺資源的不同、以及運行形態(tài)的不同,提供統(tǒng)一化的系統(tǒng)服務(wù)開發(fā)框架[system ability (SA) framework]。根據(jù)RISC-V、Cortex-M、Cortex-A不同硬件平臺,分為兩種硬件平臺,以下簡稱M核、A核。

  • M核:處理器架構(gòu)為Cortex-M或同等處理能力的硬件平臺,系統(tǒng)內(nèi)存一般低于512KB,無文件系統(tǒng)或者僅提供一個可有限使用的輕量級文件系統(tǒng),遵循CMSIS接口規(guī)范。
  • A核:處理器架構(gòu)為Cortex-A或同等處理能力的硬件平臺,內(nèi)存資源大于512KB,文件系統(tǒng)完善,可存儲大量數(shù)據(jù),遵循POSIX接口規(guī)范。

系統(tǒng)服務(wù)框架基于面向服務(wù)的架構(gòu),提供了服務(wù)開發(fā)、服務(wù)的子功能開發(fā)、對外接口的開發(fā)、以及多服務(wù)共進程、進程間服務(wù)調(diào)用等開發(fā)能力。其中:

  • M核:包含服務(wù)開發(fā)、服務(wù)的子功能開發(fā)、對外接口的開發(fā)以及多服務(wù)共進程的開發(fā)框架。
  • A核:在M核能力基礎(chǔ)之上,包含了進程間服務(wù)調(diào)用、進程間服務(wù)調(diào)用權(quán)限控制、進程間服務(wù)接口的開發(fā)等能力。

約束

  • 系統(tǒng)服務(wù)開發(fā)框架統(tǒng)一使用C開發(fā)。
  • 同進程內(nèi)服務(wù)間調(diào)用統(tǒng)一使用IUnknown接口對外象,消息接口統(tǒng)一由IUnknown接口傳遞給本服務(wù)。
  • 服務(wù)名和功能名必需使用常量字符串且長度小于16個字節(jié)。
  • M核:系統(tǒng)依賴上bootstrap服務(wù),在系統(tǒng)啟動函數(shù)中調(diào)用OHOS_SystemInit()函數(shù)。
  • A核:系統(tǒng)依賴samgr庫,在main函數(shù)中調(diào)用SAMGR_Bootstrap()函數(shù)。

再看一個完整一點的log:

看log,在 SYS_INIT(service) 這一步,bootstrap_service 首先init,

打開 base\startup\services\bootstrap_lite\source\bootstrap_service.c 查看它的 Init 函數(shù),

  1. static void Init(void) 
  2.     static Bootstrap bootstrap; 
  3.     bootstrap.GetName            = GetName; 
  4.     bootstrap.Initialize              = Initialize; 
  5.     bootstrap.MessageHandle  = MessageHandle; 
  6.     bootstrap.GetTaskConfig    = GetTaskConfig; 
  7.     bootstrap.flag = FALSE
  8.     printf("[bootstrap_service] SYS_SERVICE_INIT(Init).\n"); 
  9.  
  10.     SAMGR_GetInstance()->RegisterService((Service *)&bootstrap); 

它會先去get一個SAMGR的instance實例,向這個實例注冊bootstrap服務(wù)。

進入SAMGR_GetInstance(),在 foundation\distributedschedule\services\samgr_lite\samgr\source\samgr_lite.c文件中:

bootstrap_service 是第一個調(diào)用SAMGR_GetInstance() 的服務(wù),這時候全局變量g_samgrImpl還沒有初始化,所以就要先init,然后就可以返回instance給Bootstrap 注冊服務(wù)用了,后面的broadcast_service、hiview_service在 init時,直接就可以拿到instance去注冊了。

全局變量g_samgrImpl記錄了向它注冊的所有服務(wù)的信息,包括了一組四個函數(shù):

GetName/Initialize/MessageHandle/GetTaskConfig,這就是上面提到的“boostrap標識的入口函數(shù)”。

bootstrap_service、broadcast_service、hiview_service在SYS_INIT(service)這一步只能做很簡單的注冊服務(wù)的事情,否則會導(dǎo)致后面的INIT受阻。

在SAMGR_Bootstrap(); 這一步時,SAMGR才會真正根據(jù)注冊在g_samgrImpl的信息,逐一為已注冊的服務(wù)創(chuàng)建和分配資源,InitializeAllServices,AddTaskPool,SAMGR_StartTaskPool,SAMGR_SendSharedDirectRequest等待系統(tǒng)調(diào)度,然后在HandleInitRequest中才真正調(diào)用各自serveice注冊的Initialize接口去完成服務(wù)的啟動,為系統(tǒng)提供服務(wù)。

想了解更多內(nèi)容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)

https://harmonyos.51cto.com

 

責(zé)任編輯:jianghua 來源: 鴻蒙社區(qū)
相關(guān)推薦

2021-04-29 09:52:25

鴻蒙HarmonyOS應(yīng)用

2021-04-26 15:19:02

鴻蒙HarmonyOS應(yīng)用

2021-06-03 14:21:44

鴻蒙HarmonyOS應(yīng)用

2021-06-10 09:25:39

鴻蒙HarmonyOS應(yīng)用

2021-06-18 10:02:10

鴻蒙HarmonyOS應(yīng)用

2020-10-16 09:50:37

Hi3861WiFi熱點

2021-02-02 15:52:17

鴻蒙HarmonyOS應(yīng)用開發(fā)

2021-12-31 15:07:00

鴻蒙HarmonyOS應(yīng)用

2020-10-30 09:41:44

鴻蒙Hi3861WiFi小車

2020-11-03 11:39:22

wifi小車

2021-06-18 15:23:59

鴻蒙HarmonyOS應(yīng)用

2021-07-05 09:35:36

鴻蒙HarmonyOS應(yīng)用

2020-11-23 13:09:42

HI3861

2022-09-06 15:25:22

Wifi設(shè)備開發(fā)

2021-09-30 10:11:05

鴻蒙HarmonyOS應(yīng)用

2022-05-24 15:46:51

Wi-FiSTA模式

2022-08-19 10:54:47

操作系統(tǒng)鴻蒙

2022-10-31 15:35:02

Wi-Fi藍牙子系統(tǒng)

2021-07-07 09:45:20

鴻蒙HarmonyOS應(yīng)用

2022-09-07 15:35:49

設(shè)備開發(fā)鴻蒙
點贊
收藏

51CTO技術(shù)棧公眾號