接觸鴻蒙設備開發有一段時間了,也是時候好好挖一挖鴻蒙設備程序的啓動流程了。app
破冰問題:鴻蒙設備程序從哪裏開始運行的?ide
相信你們都已經很是清楚了,鴻蒙設備程序須要指定入口函數,具體表如今代碼層面就是經過語句 SYS_RUN(app_entry); 指定,其中 app_entry 是設備程序入口函數名;而整個鴻蒙設備的啓動流程也能夠瓜熟蒂落的挖掘出來。以下圖:函數
這看起來很是完美了,解決了全部問題!但是,我以爲仍是有不清楚的地方,即:MODULE_INIT(run) 幹了什麼事?爲何最終會調用到 app_entry() 這個入口函數?工具
接下來,咱們逐個問題的解決!post
本質問題:MODULE_INIT(run) 幹了什麼事?學習
要弄清楚這個問題,就得先來說講 SYS_RUN() 到底是什麼?!有同窗可能會認爲 SYS_RUN(app_entry); 是一個函數調用語句,將設備程序入口地址註冊到系統中,進而調用。從原理上這麼理解沒錯,可細節上根本不是那麼回事! SYS_RUN() 在用法上很像函數,但本質是一個宏!必須強調: 在 C 語言中沒法在函數以外進行函數調用,而 SYS_RUN(app_entry); 出現的位置並不在任何函數中,因此它不多是函數調用。那會是什麼呢?真相只有一個,只多是一個定義(聲明)語句。爲了證實這個結論,咱們將 SYS_RUN() 這個宏完全扒光了看個透徹。以下:ui
剖析:spa
最終,咱們能夠知道:SYS_RUN(app_entry); 是定義了一個名爲 __zinitcall_run_app_entry 的函數指針,其類型是 InitCall,不管是否使用都不會編譯報錯,而且強制編譯使其最終存放在名爲 .zinitcall.run2.init 的段中。3d
好!接下來就能夠直接分析 MODULE_INIT(run) 了。指針
MODULE_INIT(run) 展開以後根本看不出和 app_entry 有任何關係啊!咱們用了九牛二虎之力把宏掰開了,可結果貌似一無所得!!!MODULE_INIT() 和 SYS_RUN() 之間的關係仍是很是不明朗,接下來該怎麼辦呢?
仔細觀察這兩個宏拼接出來的符號!
能夠發現它們都和 zinitcall 有關,而且咱們也知道了 SYS_RUN(app_entry) 定義的全局指針就放在名爲 .zinitcall.run2.init 的段中,因此能夠推測:這個兩個宏的關係是經過連接腳本關聯的。
接下來,經過工具查看目標文件的段信息和符號信息。
經過輸出能夠知道,在名爲 .zinitcall.run2.init 的段中確實存在 __zinitcall_run_app_entry 這個符號。
以後,動手翻源碼。。。。
通過努力,咱們能夠找到 \code-1.0\vendor\hisi\hi3861\hi3861\build\build_tmp\scripts\link.lds 文件,而且發現以下的腳本代碼:
文章後續內容和附件能夠點擊下面的原文連接前往學習
原文連接:https://harmonyos.51cto.com/posts/2017#bkwz