其他文章请点击下方:
应用程序加载都会依赖底层库,库就是可执行代码(二进制) 库分为静态库和动态库。
静态库、动态库
静态库主要是扩展名.a和.lib 动态库主要是扩展名.so
编译过程
- 源文件.h、.m、.cpp
- 预编译(宏)
- 编译(高级代码)
- 汇编
- 链接(静态库和动态库)
- 可执行文件
静态库
在链接阶段,会将目标文件.o所引用的库一起打包生成可执行文件、静态链接。
动态库
在程序运行的时候,才会加进来,会多次使用,共享内存,减少打包的体积,支持热更新(不稳定、不安全) 如:我们常用UIKit就是动态库。
app加载
应用启动后,会交给动态链接器dyld去做下面的工作。
- 加载libSystem
- 通过运行时Runtime注册回调函数
/***********************************************************************
* _objc_init
* Bootstrap initialization. Registers our image notifier with dyld.
* Called by libSystem BEFORE library initialization time
**********************************************************************/
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();
lock_init();
exception_init();
//这个函数非常牛逼
_dyld_objc_notify_register(&map_images, load_images, unmap_image);
}
dyld提供一个非常重要的函数_dyld_objc_notify_register
- 加载镜像文件image
- 执行map_images和Load_images
- 调用Main函数
map_images分析
void map_images(unsigned count, const char * const paths[],
const struct mach_header * const mhdrs[])
{
mutex_locker_t lock(runtimeLock);
return map_images_nolock(count, paths, mhdrs);
}
/***********************************************************************
* _read_images
* Perform initial processing of the headers in the linked
* list beginning with headerList.
*
* Called by: map_images_nolock
*
* Locking: runtimeLock acquired by map_images
**********************************************************************/
void _read_images(header_info **hList, uint32_t hCount, int totalClasses, int unoptimizedTotalClasses)
执行map_images用到一个函数_read_images,主要处理类哈希表gdb_objc_realized_classes、方法哈希表nameSelectors、协议哈希表protocol_map
主要功能:初始化我们相应的类通过realizeClass,进行相应rw\ro操作,接下来处理分类,把分类中的属性、方法、协议加到我们相应的哈希表
load_images分析
void
load_images(const char *path __unused, const struct mach_header *mh)
{
// Return without taking locks if there are no +load methods here.
if (!hasLoadMethods((const headerType *)mh)) return;
recursive_mutex_locker_t lock(loadMethodLock);
// Discover load methods
{
mutex_locker_t lock2(runtimeLock);
prepare_load_methods((const headerType *)mh);
}
// Call +load methods (without runtimeLock - re-entrant)
call_load_methods();
}
第一步通过prepare_load_methods加载我们所有的load的方法,包括类和分类。
//通过哈希表取出类的列表
classref_t *classlist = _getObjc2NonlazyClassList(mhdr, &count);
//遍历
static void schedule_class_load(Class cls)
{
if (!cls) return;
assert(cls->isRealized()); // _read_images should realize
if (cls->data()->flags & RW_LOADED) return;
// Ensure superclass-first ordering
schedule_class_load(cls->superclass);//递归父类
add_class_to_loadable_list(cls);//类中的load加入到list中
cls->setInfo(RW_LOADED);
}
加入到list中,利用kvc
loadble_classes[loadable_classse_used].cls = cls;
loadble_classes[loadable_classes_used].method = method;
//通过哈希表取出分类的列表
category_t **categorylist = _getObjc2NonlazyCategoryList(mhdr, &count);
//分类不需要递归
realizeClass(cls);如果没有实现
//加载分类的load到list中
add_category_to_loadable_list(cat);
//加入到list中
loadable_categories[loadable_categories_used].cat = catl;
loadable_categories[loadable_categories_used].method = method;
加载完数据后,进行第二步开始进行调用call_load_methods
objc_autoreleasePoolPush() 压栈自动释放池
call_class_loads()通过指针进行方法调用
call_category_loads()
objc_autoreleasePoolPop(pool) 出栈