runloop:
保證程序不退出,負(fù)責(zé)監(jiān)聽事件,監(jiān)聽iOS的所有事件,觸摸,時鐘,網(wǎng)絡(luò)事件。
如果沒有事件會讓程序進(jìn)入休眠狀態(tài)。
//如果時鐘觸發(fā)方法,執(zhí)行非常耗的操作!! UI界面會卡。
Runloop :內(nèi)部維護(hù)事件循環(huán)來對事件/消息進(jìn)行管理的一個對象。
1.沒有消息需要處理的時候,休眠避免占用資源。不是簡單的while for循環(huán)。
2.有消息處理的時候,立刻被喚醒。
沒有消息需要處理時候,休眠以避免資源占用。
API 用戶態(tài)—內(nèi)核態(tài) (操作系統(tǒng)的指令)
有消息處理的時候。
內(nèi)核態(tài)度——用戶態(tài)。狀態(tài)的切換。
Int. main(){
執(zhí)行體 runloop接受消息,處理,等待。
}
NSRunLoop Foundation
CFRunLoop CoreFoundation .——開源
事件循環(huán),
數(shù)據(jù)結(jié)構(gòu),
CFRunloop ——pthread(線程一一對應(yīng)),
currentMode(cfrunloopmode),
modes <集合 CFRunloopMode>
.commonModes<集合 字符串>——不同模式的名稱。
comonModeltems.<集合 多個oberser timer source>
CFRunloopMode.
name. — nsdefaultRunloopMode 字符串類型。別名字符串。
sources0.——集合 無序 ——需要手動喚醒線程。 內(nèi)核態(tài)—用戶態(tài)。
sources1——集合無序—具備喚醒線程的能力。
observes—數(shù)組有序
timers—數(shù)組有序
Source
Timer:基于事件的定時器。NSTimer是免費橋轉(zhuǎn)換。
Observer.:觀測時間點。相關(guān)時間點的觀察。
1.runloopEntry:入口,啟動的時候,回掉通知。
2.beforetimer 通知觀察者,timer事件進(jìn)行處理。
3.before Source,將要處理一些source事件。
4.beforewaiting 進(jìn)入休眠狀態(tài)。
5.afterwaiting 內(nèi)核態(tài),用戶態(tài)切換。
6.exit ,退出的通知。
一個runloop /對應(yīng)一個線程 /對應(yīng)多個model/source/timer/observer/
model 屏蔽的效果。
timer 同時添加到兩個model中。
CommonMode:
NSRunLoopCommonModes.不是實際存在的一種Mode.
是同步source.timer,observer多個Mode的結(jié)局方案。
事件循環(huán)的實現(xiàn)機(jī)制:
CFRunLoopRun()
有事情做事情,沒事休息。系統(tǒng)怎么實現(xiàn)的。
1.即將進(jìn)入RunLoop.
2.將要處理Timer.
3.將要處理source0的事件
4.處理source0事件。
5.如果有source1要處理————處理喚醒消息,然后回到2 timer
6.線程將要休眠。
7.休眠等待喚醒?!猻ource1 timer 外部手動喚醒。
RunLoop核心
main()
mach_msg()—系統(tǒng)調(diào)用——核心態(tài)—mach_msg—喚醒線程。
數(shù)據(jù)結(jié)構(gòu),
事件循環(huán)機(jī)制,
runloop與NSTime:
滑動tableview的時候 我們的定時器還會生效嗎?
runloopdefaultMode,——uitrackingRunloop
cfrunloopaddTimer (runloop.timer,commonMode);打上一個標(biāo)記,同步到多個model當(dāng)中。
Runloop與多線程
線程和runloop 一一對應(yīng)的,數(shù)據(jù)結(jié)構(gòu)
默認(rèn)情況下是沒有創(chuàng)建的。
1.當(dāng)前線程開啟一個Runloop。
2.向該Runloop中添加一個Port/Source 等維持Runloop的事件。
3.啟動該Runloop。
常駐線程。
MCObject. runalways .
source1 :基于port
https://blog.csdn.net/jeffasd/article/details/52027733
http://www.itdecent.cn/u/1f93e3b1f3da
http://www.itdecent.cn/p/b4bea1549a66
②CFRunLoopSource
source是RunLoop的數(shù)據(jù)源(輸入源)的抽象類(protocol)
RunLoop定義了兩個version的Source:
i.source0:處理App內(nèi)部事件,App自己負(fù)責(zé)管理(出發(fā)),如UIEvent、CFSocket
ii.source1:由RunLoop和內(nèi)核管理,Mach Port(進(jìn)程間通訊端口)驅(qū)動,如CFMachPort、CFMessagePort
Source0只包含了一個回調(diào)(函數(shù)指針),它并不能主動觸發(fā)事件。使用時,你需要先調(diào)用 CFRunLoopSourceSignal(rlms)方法將這個Source標(biāo)記為待處理,然后手動調(diào)用CFRunLoopWakeUp(rl)方法來喚醒RunLoop,讓其處理這個事件。
//設(shè)置全局的字典,key為主線程,value為主線程關(guān)聯(lián)的RunLoop對象
CFDictionarySetValue(dict, pthreadPointer(pthread_main_thread_np()), mainLoop);
都是調(diào)用_CFRunLoopGet0函數(shù),通過源碼可知runloop的存儲方式是鍵值對,key是當(dāng)前線程,value是runloop,線程和runloop是一對一的關(guān)系,當(dāng)字典為空的時候會默認(rèn)創(chuàng)建主線程的runloop,而子線程在獲取的時候才會創(chuàng)建。
http://www.itdecent.cn/p/cfe5132e975f
1.runloop 里面包含很多的model。
2.runloop 不能創(chuàng)建,get0函數(shù)來獲取自動創(chuàng)建,跟線程一一對應(yīng),線程當(dāng)key object 是runloop 存到字典里面。
3. CFRunLoopRun
do{
0.查找currentMode是否為空。如果為空就return.
1.通知監(jiān)聽器Runloop進(jìn)入循環(huán)。
do{
2.通知監(jiān)聽器即將處理Timer事件。
3.通知監(jiān)聽器處理source0
4.執(zhí)行source0事件
5.如果有source1 (基于端口)事件 立即執(zhí)行,條轉(zhuǎn)到第九步。
6.通知監(jiān)聽器Runloop即將進(jìn)入休眠狀態(tài)。
7.將線程休眠,直到以下事件發(fā)生才會被喚醒。
mach_msg 等待接受 mach_port 的消息。線程將進(jìn)入休眠, 直到被下面某一個事件喚醒。
【 1.有source1事件到達(dá),
2.定時器出發(fā)時間到達(dá),
3.runloop 對象的超時時間過期
4.被外部顯示喚醒。
】
8通知監(jiān)聽器runloop 對象被即將喚醒。
9.處理添加進(jìn)來的事件。
1.用戶定義的定時器時間到達(dá),執(zhí)行定時器時間并重啟循環(huán),跳轉(zhuǎn)到第二部。
2.如果有source1事件,傳遞這個事件。
3.如果runloop 被顯示喚醒,并且沒有超時則重啟runloop 跳轉(zhuǎn)到第二部。
}while()
10.通知監(jiān)聽器Runloop退出循環(huán)。
}while()
3.iOS內(nèi)核
http://www.itdecent.cn/p/a1a2921f2399
1.內(nèi)核是操作系統(tǒng)中最為關(guān)鍵的部分,內(nèi)核是負(fù)責(zé)接觸底層的。用c語言寫的,有的是匯編語言。iOS的核心就是XNU內(nèi)核。
XNU:
Mach+FreeBSD+IOKit 的驅(qū)動程序
XN內(nèi)核是用于OSX iOS操作系統(tǒng)的Darwin操作系統(tǒng)的一部分。XNU是is not unix的縮寫。
XNU 是將卡內(nèi)基梅隆大學(xué)研發(fā)的 Mach 內(nèi)核與 FreeBSD 和 C ++ API 的組件相結(jié)合的混合內(nèi)核,用于編寫名為 IOKit 的驅(qū)動程序
1.由于Unix內(nèi)核是純文字界面(不像Windows內(nèi)核已經(jīng)整合了許多圖形界面的東西)
2.https://kb.cnblogs.com/page/114879/
https://bbs.feng.com/read-htm-tid-4998822.html
內(nèi)核故事
Mac OS X的底層也沿用NeXTSTEP的架構(gòu),但又有所不同。其中Mach改用一個名為osfmk的變體,BSD在2000年之后逐步轉(zhuǎn)向FreeBSD,而最慘的當(dāng)屬Driver Kit,不但改了個名叫I/O Kit,連實現(xiàn)它的編程語言都改成了C++
https://baike.baidu.com/item/MACH/216388
https://kb.cnblogs.com/page/114879/#s11
單核 :就是包含所有的服務(wù),上至內(nèi)存管理,下至設(shè)備驅(qū)動,應(yīng)有盡有。
微內(nèi)核:只包括最核心的功能(硬件訪問、調(diào)度、虛擬內(nèi)存管理)。既然微內(nèi)核存在,那么必有可取之處。相比巨內(nèi)核。
混合內(nèi)核:混合內(nèi)核試圖包含前兩種內(nèi)核好處?;旌蟽?nèi)核的核心部分支持底層服務(wù),就像微內(nèi)核一樣,而其他服務(wù)雖然不在該核心的“微內(nèi)核”中,但是也包含在該核心中,其他服務(wù)可以調(diào)用該核心的“微內(nèi)核”?;旌蟽?nèi)核相比于其他內(nèi)核架構(gòu),犧牲了微內(nèi)核的健壯性換來巨內(nèi)核一樣的運行效率。
http://www.itdecent.cn/p/a1a2921f2399
http://www.itdecent.cn/p/362bbf4cb114
http://www.itdecent.cn/p/a1a2921f2399
https://www.cnblogs.com/bakari/p/5520860.html
然用戶態(tài)下和內(nèi)核態(tài)下工作的程序有很多差別,但最重要的差別就在于特權(quán)級的不同,即權(quán)力的不同。運行在用戶態(tài)下的程序不能直接訪問操作系統(tǒng)內(nèi)核數(shù)據(jù)結(jié)構(gòu)和程序。
當(dāng)我們在系統(tǒng)中執(zhí)行一個程序時,大部分時間是運行在用戶態(tài)下的,在其需要操作系統(tǒng)幫助完成某些它沒有權(quán)力和能力完成的工作時就會切換到內(nèi)核態(tài)。
對不同的操作賦予不同的執(zhí)行等級,就是所謂特權(quán)的概念。簡單說就是有多大能力做多大的事,與系統(tǒng)相關(guān)的一些特別關(guān)鍵的操作必須由最高特權(quán)的程序來完成。Intel的X86架構(gòu)的CPU提供了0到3四個特權(quán)級,數(shù)字越小,特權(quán)越高,Linux操作系統(tǒng)中主要采用了0和3兩個特權(quán)級,分別對應(yīng)的就是內(nèi)核態(tài)和用戶態(tài)。運行于用戶態(tài)的進(jìn)程可以執(zhí)行的操作和訪問的資源都會受到極大的限制,而運行在內(nèi)核態(tài)的進(jìn)程則可以執(zhí)行任何操作并且在資源的使用上沒有限制。很多程序開始時運行于用戶態(tài),但在執(zhí)行的過程中,一些操作需要在內(nèi)核權(quán)限下才能執(zhí)行,這就涉及到一個從用戶態(tài)切換到內(nèi)核態(tài)的過程。比如C函數(shù)庫中的內(nèi)存分配函數(shù)malloc(),它具體是使用sbrk()系統(tǒng)調(diào)用來分配內(nèi)存,當(dāng)malloc調(diào)用sbrk()的時候就涉及一次從用戶態(tài)到內(nèi)核態(tài)的切換,類似的函數(shù)還有printf(),調(diào)用的是wirte()系統(tǒng)調(diào)用來輸出字符串,等等。