成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

分析鴻蒙系統helloworld程序是如何被調用,SYS_RUN做什么事情

系統
文章由鴻蒙社區產出,想要了解更多內容請前往:51CTO和華為官方戰略合作共建的鴻蒙技術社區https://harmonyos.51cto.com/?zz

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區 

https://harmonyos.51cto.com

分析 helloworld程序是如何被調用,SYS_RUN做什么事情

相信大家都已經在鴻蒙系統上實現了自己的第一個helloworld程序了。 

 

代碼很簡單,編譯燒錄后,我們就可以看到串口有打印 [DEMO] Hello world.

但是 HelloWorld 函數是在何時被調用的呢?SYS_RUN 又是干嘛的呢?

我們來看下。

1. 啟動流程

首先,我們需要分析一下Hi3861的啟動流程。目前Hi3861 使用的是liteOS-M內核,相關源碼廠家沒有提供,不過也不妨礙我們。經過我一番查找,可以知道hi3861啟動內后,第一個入口函數是 app_main函數。

(vendor\hisi\hi3861\hi3861\app\wifiiot_app\src\app_main.c)

大家可以打開,看到app_main函數的內容,如下,當然我這里只是簡版的,我刪除了很多初始化的函數,只保留最終要的。 

  1. hi_void app_main(hi_void) 
  2.  //打印sdk版本 
  3.  const hi_char* sdk_ver = hi_get_sdk_version(); 
  4.     printf("sdk ver:%s\r\n", sdk_ver); 
  5.  
  6.  //串口、IO初始化等 
  7.  peripheral_init(); 
  8.  
  9.  //wifi初始化 
  10.  ret = hi_wifi_init(APP_INIT_VAP_NUM, APP_INIT_USR_NUM); 
  11.  
  12.  
  13.  //鴻蒙系統初始化 
  14.  HOS_SystemInit(); 

我們可以看到其實app_main啟動后做了很多工作,包括io初始化、wifi初始,最后調用了HOS_SystemInit(); 進行鴻蒙系統最后的初始化。

那我們看下 HOS_SystemInit(); 做了什么動作吧。

打開源碼 base\startup\services\bootstrap_lite\source\system_init.c

可以看到函數內容如下: 

  1. void HOS_SystemInit(void) 
  2.     MODULE_INIT(bsp); 
  3.     MODULE_INIT(device); 
  4.     MODULE_INIT(core); 
  5.     SYS_INIT(service); 
  6.     SYS_INIT(feature); 
  7.     MODULE_INIT(run); 
  8.     SAMGR_Bootstrap(); 

看起來好像在調用某些模塊,仔細看,其中有一個是 MODULE_INIT(run); 。顧名思義,好像在初始化或者調用 一個 run 模塊。那run模塊又是什么呢?我們看下標題的 SYS_RUN(HelloWorld)。 是不是可以猜測其實MODULE_INIT(run); 就是調用了 HelloWorld 呢?

哈哈哈~其實還真是。大家如果加打印信息,可以看到如下打印。 

  1. ../../base/startup/services/bootstrap_lite/source/system_init.c 38  
  2.  
  3. ../../applications/sample/wifi-iot/app/my_first_app/hello_world.c 9  
  4.  
  5. [DEMO] Hello world. 
  6.  
  7. ../../base/startup/services/bootstrap_lite/source/system_init.c 40  

仔細看我加的打印語句,確實是在 38 行執行 MODULE_INIT(run); 后才打印 [DEMO] Hello world.

所以跟我們猜測的一樣。當然沒完,我們得分析為啥 是這樣。 

 

 

2. 鏈接

我們看下 MODULE_INIT(run); 做了什么。事實上,它只是一個宏。 

  1. #define MODULE_INIT(name) \ 
  2.  
  3. do { \ 
  4.  
  5. MODULE_CALL(name, 0); \ 
  6.  
  7. } while (0) 

而 MODULE_CALL(name, 0); 又可以展開:當然里面的if 語句的打印是我后面加的。 

 

我們可以看到 它其實是定義了一個 InitCall 指針,然后指針是這個: 

  1. (MODULE_BEGIN(name, step)) 

而 MODULE_BEGIN 宏其實展開后如下: 

  1. #define MODULE_NAME(name, step) ".zinitcall." #name #step ".init" 

我這里再幫大家展開,其實".zinitcall." #name #step ".init" 最后 就是 .zinitcall.run2.init

它其實是一種寫法,就是說我們代碼編譯的時候,代碼里面有一段地址比較特殊,它的名字是 .zinitcall.run2.init ,也就是說 InitCall 指針 指向的是 .zinitcall.run2.init 代碼段的地址。

畫個圖:

綠色的是.zinitcall.run2.init 代碼段,里面存放著函數指針。 

 

好了,到這里大家應該都明白了吧,繼續看這個圖,其實 這里只不過是把這個代碼段里面的所有函數指針都取出來,然后執行一下函數指針指向的函數。  

 

聰明的你應該就猜到了,.zinitcall.run2.init 代碼段里面的函數指針,指向的就是 HelloWorld 函數了~~~ 

 

到了這里就剩下最后一個問題了: 怎么讓它指向 HelloWorld 函數。

這里其實就是 SYS_RUN的功勞了。

我們也來看SYS_RUN做了什么,其它也是一個宏,展開過程如下:

我們可以看到,其實SYS_RUN(HelloWorld) 其實最終結果就是: 

  1. static const InitCall USED_ATTR __zinitcall_##layer##_##func \ 
  2.  
  3.         __attribute__((section(".zinitcall." clayer #priority ".init"))) = HelloWorld 

看起來很復雜,我們不乏拆解一下:

 

我們先不看紅色字體部分,那么結果就是:

static const InitCall = HelloWorld

是不是很簡單,其實就是定義了一個全局變量(函數指針),它指向 HelloWorld 。

那紅色字體是做什么用呢?它其實就是告訴編譯,我這個變量(static const InitCall 變量),很特殊,編譯的時候給我編譯在 .zinitcall.run2.init 段。

到了,一切都明了了,最后來一張啟動流程圖總結一下:  

 

3. 忠告

這里有兩個忠告:

1、請不要直接在SYS_RUN()定義的入口函數直接寫 while(1)

——這個很簡單理解了,因為系統啟動后,app_main會調用到 我們定義的SYS_RUN()定義的入口函數,比如HelloWorld。 如果我們在 HelloWorld 函數中寫了while(1) 就會導致 app_main 后續的代碼得不到執行,肯定有問題。

2、SYS_RUN()定義的入口函數創建的線程,請一定要有sleep動作。

為了解決第一個問題,我們很自然地想到,可以在 SYS_RUN()定義的入口函數 創建線程,這樣就可以while(1)了。哈哈,其實也是有問題,因為 app_main 本身也是一個任務,如果我們自己創建地任務優先級特別高,就會導致 app_main 任務不會被執行,還是有問題。所以要有sleep,確保 app_main 后續地代碼能順利執行下去。

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區

https://harmonyos.51cto.com

 

責任編輯:jianghua 來源: 鴻蒙社區
相關推薦

2020-06-08 15:15:26

程序員擺地攤技術

2020-07-09 11:57:50

機器學習函數學習

2024-03-28 10:40:43

javanew關鍵字

2020-12-15 09:33:40

鴻蒙Hi3861開發板

2022-05-24 07:57:06

前端監控系統

2012-11-26 10:58:33

2020-11-04 16:00:22

文件系統

2013-07-15 17:17:20

2022-01-07 17:28:07

操作系統IO 內存

2019-04-29 15:27:57

網絡故障工具

2021-04-30 20:20:36

HugePages大內存頁系統

2010-08-20 09:52:36

丁磊管理

2024-04-01 08:23:20

代碼Javajavascript

2022-02-09 10:56:09

ReactJS組件前端

2023-03-03 09:11:55

軟件開發NASA

2017-05-17 14:51:31

DNS架構負載均衡

2018-05-23 12:29:36

2022-09-24 13:29:42

Spring操作SQL

2024-02-19 12:24:58

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 视频在线一区 | 国产无套一区二区三区久久 | 三级黄色网址 | 国产精品久久久久久久久 | 狠狠操婷婷 | a在线免费观看 | 久久综合伊人一区二区三 | 久久婷婷色 | 狠狠操操 | 四虎成人av | 精品亚洲一区二区三区四区五区 | 亚洲一区二区三区免费视频 | 午夜影院在线免费观看视频 | 第一区在线观看免费国语入口 | 国产精品久久网 | 国内精品视频在线观看 | 国产精品一区二区三区久久久 | 中文字幕精品视频在线观看 | 国产三区在线观看视频 | 欧美极品在线播放 | 午夜影院在线观看 | 欧美一级片在线观看 | 欧美aⅴ| 人人草人人干 | 亚洲欧美综合精品另类天天更新 | 久久久一区二区三区 | 国产精品成人在线观看 | 亚洲一区二区三区高清 | xnxx 日本免费 | 永久av| 最新日韩在线 | 欧美四虎 | 国产精品一区视频 | 亚洲一区视频在线 | 日本黄色片免费在线观看 | a在线观看| 欧美久久久久久久久 | 一本大道久久a久久精二百 欧洲一区二区三区 | 久久婷婷av | 国产在线精品一区二区三区 | 亚洲欧美精品国产一级在线 |