iOS底層原理 12 : 應用程序的加載

一、應用程序的加載

APP加載過程:程序啟動依次加載dyldlibSystemlibdispathc.dyldlibobjc動態庫,最終調用_objc_init()方法,在此方法中Runtime向dyld注冊回調函數,加載新的image,執行map_imagesload_imagesimageLoader加載image,調用main函數

二、dyld動態鏈接器

dyld(the dynamic link editor)是蘋果的動態鏈接器,是蘋果操作系統一個重要組成部分,在系統內核做好程序準備工作之后,交由dyld負責余下的工作。

1.dyld的加載過程:
1.環境變量的配置
2.共享緩存 checkSharedRegionDisable()
3.主程序的初始化
4.加入動態庫 loadInsertedDylib()
5.link主程序 link(sMainExecutable, sEnv.DYLD_BIND_AT_LAUNCH, true, ImageLoader::RPathChain(NULL, NULL), -1)
6.link動態庫 link(image, sEnv.DYLD_BIND_AT_LAUNCH, true, ImageLoader::RPathChain(NULL, NULL), -1)
7.initializeMainExecutable運行所有初始化程序
8.main notifyMonitoringDyldMain()

2.reloadAllImages加載鏡像文件的步驟:

  • 實例化主程序instantiateFromLoadedImage(),內核會映射到主要可執行文件中,我們需要為映射到主可執行文件的文件,創建ImageLoader。在此方法中,然后讀取image,然后addImage()讀取加載鏡像文件。會先在instantiateMainExecutable()中,會確認此mach-o文件中是否具有壓縮的LINKEDIT以及段數。
  • 加載插入任何動態庫loadInsertedDylib(*lib),將其讀取為鏡像文件iamge。
  • 鏈接庫。先遍歷,讀取image,然后link。在link中,遞歸插入動態加載的鏡像文件。

3.initializeMainExecutable()運行所有初始化程序步驟:

  • runInitializers()
  • processInitializers初始化準備。
  • processInitializers中,遍歷iamge.count,遞歸一個個開始初始化條件images[i]->recursiveInitialization
  • 在遞歸開始初始化條件中recursiveInitialization,通過notifySingle方法,對單個鏡像通知開始初始化。獲取鏡像文件的真實地址(*sNotifyObjCInit)(image->getRealPath(), image->machHeader()), 而notifySingle中的sNotifyObjCInit是在objc_init()中注冊傳遞過來的,所以只有當objc_init()調用時,重新加載image
  • notifySingle方法之后,遍歷初始化this->doInitialization(context)
  • 在doInitialization方法中,先調用doImageInit(context),確保libSystem庫必須提前初始化完成。再調用doModInitFunctions()方法,對 C++和構造函數處理,然后調用libSystem_initializer方法,調用libdispatch_init,調用_os_object_init,最終調用_objc_init方法。
  • _objc_init方法來注冊回調函數,重新加載images,執行map_imagesload_imagesimageLoader加載image,調用main函數。

面試題

1.main()之前系統做了哪些工作?

1)dyld 開始將程序二進制文件初始化

2)交由ImageLoader讀取 image,其中包含了我們的類,方法等各種符號(Class、Protocol 、Selector、 IMP)

3)由于runtimedyld 綁定了回調,當image加載到內存后,dyld會通知runtime進行處理

4)runtime 接手后調用map_images做解析和處理

5)接下來load_images中調用call_load_methods方法,遍歷所有加載進來的Class,按繼承層次依次調用Class+load和其他Category+load方法

6)至此 所有的信息都被加載到內存中

7)最后dyld發送調main函數的通知,接下來就是main函數

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。