LLDB結(jié)合底層源碼分析Cache數(shù)據(jù)結(jié)構(gòu)

我再來分享一個底層知識點另伍,學(xué)到了之后不寫出來總覺得不是自己的,關(guān)于cache的數(shù)據(jù)結(jié)構(gòu)愁茁,首先cache是什么呢?

這個英文單詞就是緩存的意思亭病,那他緩存的是什么呢鹅很?我們大多數(shù)人肯定都不太了解,我之前獲取bits罪帖,可以進行內(nèi)存平移促煮,那我獲取cache是不是也可以進行內(nèi)存平移呢邮屁?

一試便知,我在objc的源碼工程里面寫了一個demo菠齿,自定義了一個類 LGPerson 繼承自 NSObject佑吝,來到main里面,通過 class 拿到這個類绳匀,然后在下一行打一個斷點芋忿,如下圖。

圖片

運行疾棵,停在斷點處之后戈钢,我來進行萬能的LLDB調(diào)試。

圖片

拿到 pClass 的地址之后給他打印出來是尔,但是直接打印是不行的殉了,還要進行一下強轉(zhuǎn)。

圖片

強轉(zhuǎn)之前拟枚,我先給他平移16個字節(jié)薪铜,就是加10,變成了0x0000000100008460恩溅,然后強轉(zhuǎn)的話隔箍,轉(zhuǎn)成什么類型呢?

就是 cache 的類型暴匠,那 cache 是什么類型我不記得了鞍恢,我就去源碼里面找一下,全局搜索objc_class每窖。

圖片

可以在后面加一個空格帮掉,結(jié)果會少很多,找到 new.h結(jié)尾的文件窒典,然后里面就有這個 objc_class 結(jié)構(gòu)體蟆炊,點進去。

圖片

這里就找到了cache瀑志,這個過程需要對底層原理有比較好的掌握涩搓,cache 是什么類型就一目了然了,是一個cache_t 類型劈猪,我拷貝出來昧甘,加個星號表示還原他的指針。

圖片

回車就得到了 cache_t 類型的 $1战得,然后我來看里面的數(shù)據(jù)充边。

圖片

打印得到了這么一長串內(nèi)容,主要有這么幾個變量名:_bucketsAndMaybeMask、_maybeMask浇冰、_flags贬媒、_occupied、_originalPreoptCache肘习。

那這些東西我看不懂际乘,不知所云,所以我需要在源碼里面找到對應(yīng)的說辭漂佩,怎么找呢脖含,我 command 點擊 cache_t,Jump to Definition投蝉。

圖片

很明顯器赞,cache_t 也是一個結(jié)構(gòu)體,然后有一個private墓拜,里面就有這個 _bucketsAndMaybeMask 等一些變量。

跟我打印出來的一模一樣请契,除了 _bucketsAndMaybeMask之外咳榜,其他幾個都被 union 一個大括號包進去了,他們是一個聯(lián)合體爽锥。

很多人可能對于這種結(jié)構(gòu)不那么了解涌韩,我再來補充一個點,在真機上的app氯夷,是運行在 arm64 架構(gòu)上的臣樱,模擬器呢?i386腮考,Mac呢雇毫?

x86_64,M1 的 Mac 也是 arm64踩蔚,這是跟硬件有關(guān)的棚放,那這個聯(lián)合體里面有一個 #if LP64 是什么呢?LP64 就是適用在 Linux 和 macOS 電腦上面的一個數(shù)據(jù)模型馅闽,我找了個表格給大家看一下飘蚯。

圖片

就很明顯了,LP64 就是指代 Unix 系列的操作系統(tǒng)福也,所以都是跑的64位局骤,也就是說,這個 if 條件是成立的暴凑。

整個 cache_t 的數(shù)據(jù)結(jié)構(gòu)就能夠很清晰很直觀的了解了峦甩,那么問題來了,cache是緩存搬设,那到底緩存什么呢穴店?要么緩存屬性撕捍,要么緩存方法,這里我看到了屬性泣洞,但是沒看到方法忧风。

按理說也應(yīng)該緩存方法才對,如果是緩存方法的話球凰,我應(yīng)該在這個結(jié)構(gòu)體里面能看到 sel 和 imp狮腿,但是并沒有,是不是意味著他不是緩存這些東西呢呕诉?我先賣個關(guān)子缘厢。

接下來又有一個問題,這幾個屬性里面甩挫,哪一個才是我們需要關(guān)注的贴硫、最重要的那個?打印信息里面兩個沒有值的可以排除伊者,剩下的我也不知道哪個最重要英遭,那怎么辦呢?

這里又有一個閱讀源碼的小技巧亦渗,就是看他提供的功能方法挖诸,這個cache_t,是一個緩存法精,也就必定是一個存儲的過程多律,意味著他一定會有東西進行了讀寫,或者增刪改查等等的操作搂蜓。

所以狼荞,我再繼續(xù)往下找方法,在481行就找到了一個 insert洛勉,也就是插入粘秆,正好命中了我剛剛的猜想,他離不開增刪改查收毫,并且他的參數(shù)正好就有 sel 和 imp攻走。

圖片

所以,我來看看他里面有沒有我想要的東西此再,點進去昔搂,看到了兩個 sel(),都是由 bucket_t 對象中的元素進行調(diào)用输拇,也就是對 bucktet_t 進行了一些操作摘符,難道關(guān)鍵就在bucket_t ?(下圖源碼進行了一些刪減)

圖片

正好在之前的 cache_t 結(jié)構(gòu)體中找 insert 的時候也看到了不少 bucket_t。

圖片

感覺他的重心應(yīng)該就是這個bucket_t逛裤,我直接點進去瘩绒,看到如下圖的內(nèi)容。

圖片

這就恍然大明白了带族,就是千呼萬喚的 imp 和 sel锁荔,bucket 單詞是“桶”的意思,就是一個容器蝙砌,裝了很多的imp 和 sel阳堕,并且一個 imp 就對應(yīng)了一個 sel,梳理一下择克。

cache 里面有一個 buckets恬总,buckets 里面就會有一個 sel 和 imp,但是這個具體的結(jié)構(gòu)肚邢,我還不是非常的清楚壹堰,但是知道這么多就已經(jīng)足夠了。

圖片

然后我要去驗證里面的值骡湖,是不是真的有缀旁,是不是真的是這樣的呢?眼見不一定為實勺鸦,自己操作一遍才放心,那我繼續(xù)LLDB調(diào)試目木。

之前已經(jīng)拿到了$2函匕,然后他的重點是buckets鸭轮,所以我是不是應(yīng)該打印這個_bucketsAndMaybeMask 呢?只有這個里面有 buckets 這個詞,試一試饰躲。

圖片

然后我去拿他的Value,因為也沒其他東西可以拿唇牧。

圖片

竟然拿不到风范!又進了死胡同,LLDB調(diào)試不出來了摹恰,怎么辦辫继?這個時候又回到了上面提到的調(diào)試技巧,我只能去找他有沒有合適的方法俗慈。

這是LLDB調(diào)試遇到問題的時候最常見的辦法姑宽,那我去 cache_t 結(jié)構(gòu)體中找一下是不是有g(shù)et相關(guān)的方法,別說闺阱,還真有炮车。

圖片

這里得到了一個結(jié)構(gòu)體指針 buckets,感覺事情變得簡單了,我拷貝 buckets() 繼續(xù)進行調(diào)試瘦穆。

圖片

果真拿到了一個 bucket_t 的地址纪隙,那這個地址里面是什么我也不知道,打印出來看一下扛或。

圖片

跟之前的源碼分析一模一樣绵咱,就是 imp 和 sel,但是他們什么都沒有告喊,很尷尬麸拄,不過也沒關(guān)系,我這里已經(jīng)可以得到一些信息了黔姜,bucket_t 結(jié)構(gòu)體里面是有一個 #if 判斷的拢切。

圖片

這個條件語句里面,我是走的 if 還是 else 呢秆吵,我都不用分析這個條件淮椰,對比一下打印出來的 $4 就知道了,先 imp纳寂,然后 sel主穗,所以走的是 arm64,大多數(shù)人在這里應(yīng)該都是走的 else毙芜,為什么呢忽媒?

因為我是M1的Mac,我已經(jīng)走在了時尚的最前沿腋粥,哈哈哈晦雨,大多數(shù)人都是 x86,所以走的是 else隘冲,如果是真機環(huán)境的話闹瞧,走的也是 arm64,其實區(qū)別不大展辞,了解一下就好了奥邮。

但是他們?yōu)槭裁炊紱]有呢?因為沒有調(diào)用方法罗珍!沒有調(diào)用方法洽腺,他有個LLDB的緩存啊,那我再來調(diào)用一下方法覆旱,這個 LGPerson 我已經(jīng)寫好了一個實例方法 saySomething已脓。

圖片
圖片

調(diào)完方法之后,上面的流程我再來一次通殃。

圖片

imp 的 Value 不出所料有值了度液!但是你們操作的時候厕宗,可能還是會沒有東西,如果你們沒有的話堕担,怎么辦呢已慢?

我也提一嘴,這是一個 buckets霹购,他有個s字母結(jié)尾佑惠,就意味著他是一個數(shù)組,所以你可以在后面加上一個[1]齐疙,取他下一個bucket膜楷,或許你就有值了。

如果沒有多個就可以直接取贞奋,這里涉及到了哈希函數(shù)赌厅,因為哈希函數(shù)的下標是不一定的,普通的數(shù)組是從零開始的轿塔,但是哈希就不同特愿,而且他還是無序的。

但是這個 $10 還不是我想看到的結(jié)果勾缭,我想看的是最終打印出 saySomething揍障,才能證明我們的源碼分析沒有問題,那我還是同樣的來看 bucket_t 結(jié)構(gòu)體里面有沒有相應(yīng)的方法俩由。

圖片

找到一個 sel()毒嫡,不解釋了,直接拿過來用幻梯。

圖片

打印出了 saySomething审胚,就這?簡單得很嘛礼旅,所以,我也應(yīng)該同樣的可以改成 imp()洽洁。

圖片

竟然報錯了痘系,問題不大,這個錯誤提示很熟悉饿自,翻譯過來就是參數(shù)太少了汰翠,預(yù)想的是有2個參數(shù),但是我沒有給昭雌,只有0個复唤,如果你也這么操作了,說明你肯定沒有去仔細看源碼烛卧,imp() 就在 sel() 下面一點點佛纫。

圖片

這里他需要兩個參數(shù)妓局,一個 bucket_t,一個 class呈宇,這個 class 我可以給你好爬,很簡單,就是 pClass甥啄,那這個bucket_t 我怎么給存炮?我不知道,我也不想知道蜈漓,感覺很麻煩的亞子穆桂,那我直接丟個 nil,回車融虽。

圖片

漂亮享完,來自 KCObjcBuild 里面的 LGPerson 的實例方法 saySomething,完美打印出來衣形,到這里驼侠,cache的數(shù)據(jù)結(jié)構(gòu)分析,就基本搞定谆吴,到此結(jié)束倒源。

最后呢,如果對于文章內(nèi)容有任何疑問都可以進行留言句狼,objc源碼我就不放了笋熬,網(wǎng)上一大把,如果某些內(nèi)容有誤也懇請幫我指出來腻菇,共同進步胳螟。

轉(zhuǎn)載:https://mp.weixin.qq.com/s/RFZ35hNotUcYlt0pEnWNHw

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市筹吐,隨后出現(xiàn)的幾起案子糖耸,更是在濱河造成了極大的恐慌,老刑警劉巖丘薛,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嘉竟,死亡現(xiàn)場離奇詭異,居然都是意外死亡洋侨,警方通過查閱死者的電腦和手機舍扰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來希坚,“玉大人边苹,你說我怎么就攤上這事〔蒙” “怎么了个束?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵慕购,是天一觀的道長。 經(jīng)常有香客問我播急,道長脓钾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任桩警,我火速辦了婚禮可训,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘捶枢。我一直安慰自己握截,他們只是感情好,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布烂叔。 她就那樣靜靜地躺著谨胞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蒜鸡。 梳的紋絲不亂的頭發(fā)上胯努,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天,我揣著相機與錄音逢防,去河邊找鬼叶沛。 笑死,一個胖子當著我的面吹牛忘朝,可吹牛的內(nèi)容都是我干的灰署。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼局嘁,長吁一口氣:“原來是場噩夢啊……” “哼溉箕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起悦昵,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤肴茄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后但指,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寡痰,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年枚赡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谓谦。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡贫橙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出反粥,到底是詐尸還是另有隱情卢肃,我是刑警寧澤疲迂,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站莫湘,受9級特大地震影響尤蒿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜幅垮,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一腰池、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧忙芒,春花似錦示弓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至潮峦,卻和暖如春囱皿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背忱嘹。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工嘱腥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人德谅。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓爹橱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親窄做。 傳聞我的和親對象是個殘疾皇子愧驱,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容