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

相关文章
相关标签/搜索