iOS底層探索--dyld與objc的關聯

小谷底層探索合集緩存

兄弟們。十一假期玩的爽嗎。小生睡了7天,可謂是美滋滋啊。😆markdown

  • 你們對於應用的啓動過程應該有些瞭解了,因爲我偷懶(在睡覺),因此就沒有寫應用啓動的博客了)

1. 應用的啓動流程簡析

我就簡單的寫下哈。。就不帶你們一步一步走了(見諒見諒~),你們有時間的話仍是能夠調試走一波的。app

    1. 我很是努力的畫了個圖:

有點簡陋。函數

    1. 咱們得出結論,應用啓動首先調用的是_dyld_start,而後調用objc源碼

的第一個方法是_objc_init(這個就是今天要研究的東西~)oop

2. _objc_init初探

    1. 首先咱們看下源碼:
void _objc_init(void)
{
    static bool initialized = false;
    if (initialized) return;
    initialized = true;
    
    // fixme defer initialization until an objc-using image is found?
    environ_init();
    tls_init();
    static_init();
    runtime_init();
    exception_init();
    cache_init();
    _imp_implementationWithBlock_init();

    _dyld_objc_notify_register(&map_images, load_images, unmap_image);

#if __OBJC2__
    didCallDyldNotifyRegister = true;
#endif
}
複製代碼
    1. 來一波專有名詞解釋~
environ_init(); 						//環境變量的讀取初始化
tls_init(); 							//自動釋放池、runloop線程相關
static_init();							//運行C ++靜態構造函數
runtime_init();							//新增的。runtime運行時環境初始化
exception_init();						//異常捕獲初始化
cache_init();							//緩存條件初始化
_imp_implementationWithBlock_init();	//啓動回調機制
複製代碼

好吧,以上都不是要探究的重點~😆,這裏先不作解釋了。源碼分析

    1. _dyld_objc_notify_register探究

_dyld_objc_notify_register是此次探究的。肉眼可見和dyld有關聯~ 咱們點進去以後發現:跟不進去了~post

3. dyld源碼分析

    1. 既然在objc源碼中不能繼續探究,並且還和dyld有關聯,那咱們想一想一下會不會調用了dyld源碼。
    1. 咱們打開dyld源碼發現:
void _dyld_objc_notify_register(_dyld_objc_notify_mapped    mapped,
                                _dyld_objc_notify_init      init,
                                _dyld_objc_notify_unmapped  unmapped)
{
     dyld::registerObjCNotifiers(mapped, init, unmapped);
}
複製代碼
    1. 既然找到了~ 那咱們能夠猜想一波:這個是跨庫調用(沒得辦法這個就是這麼噁心)
    1. 咱們分析下他調用的源碼:
void registerObjCNotifiers(_dyld_objc_notify_mapped mapped, _dyld_objc_notify_init init, _dyld_objc_notify_unmapped unmapped) {
     // record functions to call
     sNotifyObjCMapped    = mapped;
     sNotifyObjCInit        = init;
     sNotifyObjCUnmapped = unmapped;


     // call 'mapped' function with all images mapped so far
     try {
         notifyBatchPartial(dyld_image_state_bound, true, NULL, false, true);
     }
     catch (const char* msg) {
         // ignore request to abort during registration
     }


     // <rdar://problem/32209809> call 'init' function on all images already init'ed (below libSystem)
     for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
         ImageLoader* image = *it;
         if ( (image->getState() == dyld_image_state_initialized) && image->notifyObjC() ) {
             dyld3::ScopedTimer timer(DBG_DYLD_TIMING_OBJC_INIT, (uint64_t)image->machHeader(), 0, 0);
             (*sNotifyObjCInit)(image->getRealPath(), image->machHeader());
         }
     }
}
複製代碼
    1. 嘿咻~,這個時候我要截個圖了~(代碼上寫註釋,顏色不給力😆)

    1. 那這個的意思:objc源碼跨庫調用dyld源碼,而後dyld源碼在調用了objc源碼~

4. 應用啓動流程圖擴展

    1. 咱們已經清楚:應用啓動首先調用的是_dyld_start,而後調到_objc_init,以後又跨庫調用了dyld,而後目的仍是調用map_imagesload_images.
    1. 感受好繞。😭。那麼我畫了一幅擴展的圖:

兄弟們~ 這幅圖我盡力了畢竟不是靈魂畫家😆ui

相關文章
相關標籤/搜索