dyld加載流程
配置環(huán)境變量依賴DYLD(dyld)
dyld(the dynamic link editor)是蘋果的動(dòng)態(tài)鏈接器翁授,是蘋果操作系統(tǒng)的重要組成部分糊治,在app被編譯打包成可執(zhí)行文件格式的Mach-O文件后轻庆,交由dyld負(fù)責(zé)連接阵谚,加載程序
app啟動(dòng)的起始點(diǎn)
【app啟動(dòng)起點(diǎn)】:通過程序運(yùn)行發(fā)現(xiàn),是從dyld中的_dyld_start開始的乌妙,
源碼中搜索dyldbootstrap找到命名作用空間森书,再在這個(gè)文件中查找start方法靶端,其核心是返回值的調(diào)用了dyld的main函數(shù)
在_main函數(shù)中主要做了一下幾件事情:
【第一步:環(huán)境變量配置】:根據(jù)環(huán)境變量設(shè)置相應(yīng)的值以及獲取當(dāng)前運(yùn)行架構(gòu)
【第二步:共享緩存】:檢查是否開啟了共享緩存,以及共享緩存是否映射到共享區(qū)域凛膏,例如UIKit杨名、CoreFoundation等
【第三步:主程序的初始化】:調(diào)用instantiateFromLoadedImage函數(shù)實(shí)例化了一個(gè)ImageLoader對象
【第四步:插入動(dòng)態(tài)庫】:遍歷DYLD_INSERT_LIBRARIES環(huán)境變量,調(diào)用loadInsertedDylib加載
【第五步:link 主程序】
【第六步:link 動(dòng)態(tài)庫】
【第七步:弱符號(hào)綁定】
【第八步:執(zhí)行初始化方法】
【第九步:尋找主程序入口即main函數(shù)】:從Load Command讀取LC_MAIN入口猖毫,如果沒有台谍,就讀取LC_UNIXTHREAD,這樣就來到了日常開發(fā)中熟悉的main函數(shù)了
第三步:主程序初始化
sMainExecutable表示主程序變量鄙麦,查看其賦值典唇,是通過instantiateFromLoadedImage方法初始化
進(jìn)入instantiateFromLoadedImage源碼,其中創(chuàng)建一個(gè)ImageLoader實(shí)例對象胯府,通過instantiateMainExecutable方法創(chuàng)建
進(jìn)入instantiateMainExecutable源碼介衔,其作用是為主可執(zhí)行文件創(chuàng)建映像,返回一個(gè)ImageLoader類型的image對象骂因,即主程序炎咖。其中sniffLoadCommands函數(shù)時(shí)獲取Mach-O類型文件的Load Command的相關(guān)信息,并對其進(jìn)行各種校驗(yàn)
上面的第八步:執(zhí)行初始化方法
進(jìn)入initializeMainExecutable源碼,主要是循環(huán)遍歷寒波,都會(huì)執(zhí)行runInitializers方法
notifySingle 函數(shù)
發(fā)現(xiàn)在_dyld_objc_notify_register進(jìn)行了調(diào)用
_dyld_objc_notify_register乘盼,發(fā)現(xiàn)在_objc_init源碼中調(diào)用了該方法,并傳入了參數(shù)俄烁,所以sNotifyObjCInit的賦值的就是objc中的load_images绸栅,而load_images會(huì)調(diào)用所有的+load方法。所以綜上所述页屠,notifySingle是一個(gè)回調(diào)函數(shù)
load函數(shù)加載
下面我們進(jìn)入load_images的源碼看看其實(shí)現(xiàn)粹胯,以此來證明load_images中調(diào)用了所有的load函數(shù)
通過objc源碼中_objc_init源碼實(shí)現(xiàn),進(jìn)入load_images的源碼實(shí)現(xiàn)
進(jìn)入call_load_methods源碼實(shí)現(xiàn)辰企,可以發(fā)現(xiàn)其核心是通過do-while循環(huán)調(diào)用+load方法
【總結(jié)】load的源碼鏈為:_dyld_start --> dyldbootstrap::start --> dyld::_main --> dyld::initializeMainExecutable --> ImageLoader::runInitializers --> ImageLoader::processInitializers --> ImageLoader::recursiveInitialization --> dyld::notifySingle(是一個(gè)回調(diào)處理) --> sNotifyObjCInit --> load_images(libobjc.A.dylib)