tlb - translation lookaside buffer
快表。直譯為翻譯後備緩衝器,也能夠理解為頁表緩衝。位址變換快速快取。
因為頁表存放在主存中,因此程式每次訪存至少須要兩次:一次訪存獲取實體地址,第二次訪存才獲得資料。
提高訪存效能的關鍵在於依靠頁表的訪問區域性性。
當乙個轉換的虛擬頁號被使用時,它可能在不久的將來再次被使用到,。
tlb是一種快速快取,記憶體管理硬體使用它來改善虛擬位址到實體地址的轉換速度。
當前全部的個人桌面,筆記本和server處理器都使用tlb來進行虛擬位址到實體地址的對映。使用tlb核心能夠快速的找到虛擬位址指向實體地址,而不須要請求ram記憶體獲取虛擬位址到實體地址的對映關係。這與data cache和instruction caches有非常大的相似之處。
tlb原理
想像一下x86_32架構下沒有tlb的存在時的情況,對線性位址的訪問,首先從pgd中獲取pte(第一次記憶體訪問)。在pte中獲取頁框位址(第二次記憶體訪問)。最後訪問實體地址,總共須要3次ram的訪問。假設有tlb存在,而且tlb hit。那麼僅僅須要一次ram訪問就可以。
tlb表項
tlb內部存放的基本單位是頁表條目,相應著ram中存放的頁表條目。頁表條目的大小固定不變的,所以tlb容量越大,所能存放的頁表條目越多。tlb hit的機率也越大。可是tlb容量畢竟是有限的,因此ram頁表和tlb頁表條目無法做到一一相應。
1 所需的也表示否已經快取在tlb內部(tlb miss或者tlb hit)
2 所需的頁表在tlb的哪個條目內
為了盡量降低cpu做出這些推斷所需的時間,那麼就必須在tlb頁表條目和記憶體頁表條目之間的相應方式做足功夫
全相連 - full associative
在這樣的組織方式下。tlb cache中的表項和線性位址之間沒有不論什麼關係。也就是說,乙個tlb表項能夠和隨意線性位址的頁表項關聯。這樣的關聯方式使得tlb表項空間的利用率最大。
可是延遲也可能相當的大,由於每次cpu請求,tlb硬體都把線性位址和tlb的表項逐一比較,直到tlb hit或者全部tlb表項比較完畢。特別是隨著cpu快取越來越大,須要比較大量的tlb表項,所以這樣的組織方式僅僅適合小容量tlb
直接匹配
每個線性位址塊都可通過模運算相應到唯一的tlb表項,這樣僅僅需進行一次比較,減少了tlb內比較的延遲。可是這個方式產生衝突的機率很高。導致tlb miss的發生。減少了命中率。
比方。我們假定tlb cache共包括16個表項。cpu順序訪問下面線性位址塊:1, 17 , 1, 33。
當cpu訪問位址塊1時,1 mod 16 = 1。tlb檢視它的第乙個頁表項是否包括指定的線性位址塊1,包括則命中,否則從ram裝入。然後cpu方位位址塊17,17 mod 16 = 1,tlb發現它的第乙個頁表項相應的不是線性位址塊17。tlb miss發生。tlb訪問ram把位址塊17的頁表項裝入tlb;cpu接下來訪問位址塊1,此時又發生了miss,tlb僅僅好訪問ram又一次裝入位址塊1相應的頁表項。因此在某些特定訪問模式下。直接匹配的效能差到了極點
組相連 - set-associative
為了解決全相連內部比較效率低和直接匹配的衝突,引入了組相連。這樣的方式把全部的tlb表項分成多個組,每乙個線性位址塊相應的不再是乙個tlb表項。而是乙個tlb表項組。cpu做位址轉換時,首先計算線性位址塊相應哪個tlb表項組,然後在這個tlb表項組順序比對。依照組長度,我們能夠稱之為2路,4路。8路。
經過長期的project實踐,發現8路組相連是乙個效能分界點。8路組相連的命中率差點兒和全相連命中率差點兒一樣,超過8路。組內對照延遲帶來的缺點就超過命中率提高帶來的優點了。
這三種方式各有優缺點,組相連是個折衷的選擇。適合大部分應用環境。當然針對不同的領域,也能夠採用其它的cache組織形式。
tlb表項更新
tlb表項更新能夠有tlb硬體自己主動發起。也能夠有軟體主動更新
1. tlb miss發生後。cpu從ram獲取頁表項,會自己主動更新tlb表項
2. tlb中的表項在某些情況下是無效的,比方程序切換。更改核心頁表等。此時cpu硬體不知道哪些tlb表項是無效的,僅僅能由軟體在這些場景下。重新整理tlb。
在linux kernel軟體層,提供了豐富的tlb表項重新整理方法,可是不同的體系結構提供的硬體介面不同。比方x86_32僅提供了兩種硬體介面來重新整理tlb表項:
1. 向cr3暫存器寫入值時,會導致處理器自己主動重新整理非全域性頁的tlb表項
2. 在pentium pro以後,invlpg彙編指令用來無效指定線性位址的單個tlb表項無效。
tlb重新整理機制
在mmu開啟的情形下。線性地 址到實體地址的轉換須要經過頁表的查詢。假設每次都這麼做的話顯然對系統效能有影響。因此出現了這麼乙個cache,用來將已經此前的查詢結果儲存在這個 tlb中。顯然tlb由於容量的限制不可能將全部的線性位址到實體地址的轉換全部容納進去,當tlb中全部的entry都被放置滿的時候。處理器會決定將 乙個舊的entry替換掉。
tlb本質上就是一塊cache。所以也存在cache一致性的問題。比方假設作業系統改動了頁表中的某一項 的對映關係,假設該項的對映恰好儲存在tlb中。那麼就出現了一致性的問題。與x86下系統物理記憶體與處理器間的cache一致性不一樣,tlb的一致性 須要系統軟體出面解決,而不是硬體。x86為此提供了兩種方式來解決tlb一致性的問題:
1. 更新cr3. 假設cr3暫存器被又一次載入。那麼會導致整個tlb無效。os能夠通過比方: mov eax, cr3; move cr3, eax;這種指令來重新整理整個tlb。還有,我們知道linux下程序切換時,會又一次載入cr3暫存器。由於新老程序的頁表項是不同樣的。因此須要使 tlb無效防止出現不一致的情況。
2. x86提供了一條invlpg指令。該指令是特權指令。作業系統能夠通過該指令對tlb中的單獨的某一entry進行更新。
__flush_tlb_single函式來重新整理tlb中的項(詳細哪一項由虛擬線性位址addr來指定)。__flush_tlb_single的實現是:
static inline void __native_flush_tlb_single(unsigned long addr)
上面是乙個很直觀的invlpg指令使用範例。在__flush_tlb_one函式中。我們還能夠看到__flush_tlb的呼叫,後者被用來重新整理整個tlb,事實上就是本文前面提到的用mov指令倒換一下重寫cr3.
在分頁機制開啟的情形下。當cpu要訪問乙個線性位址時,首先會查詢tlb,假設該線性位址的轉換已經儲存在tlb賓果,因此,直接訪問實體地址(的確tlb它儲存在vpn和ppn製圖),在這一點上,你並不需要檢查頁資料夾頁表。
假定當前的線性位址對映尚未儲存tlb在,然後是一tlb miss,在這一點上,你需要找到該網頁資料夾和頁表項。然後結果被對映到記錄tlb在。
Linux x86棧溢位攻擊實驗 寫在前面的話
說,要想在安全這個行業走得遠,首先要看興趣。其實我有些懷疑自己的興趣,不過幹一行愛一行。接下來就開始我們linux環境下的準備工作啦 敲重點!兩個踩過的大坑 1 務必使用64位機器,pwntools不支援32位python 2 32位機器只能編譯生成32位程式,64位機器可以生成32位和64位程式,...
Linux X86 PS 2鍵盤驅動分析記錄
1,linux x86 ps 2 鍵盤驅動框架流程 以下均已intel 8042鍵盤控制器為例 1.1 裝置初始化註冊流程 鍵盤控制器硬體驅動 i8042.c 串列埠驅動核心 serio.c 串列埠驅動 atkbd.c 輸入驅動核心 input.c 輸入事件驅動程式 keyboard.c 虛擬控制台...
在VC下配置執行JM86
編碼 4 滑鼠左鍵選中 lencod 工程 5 開啟 project settings debug 在 working directory 選項中填寫 bin,在 program arguments 選項中填寫需要使用的編碼配置檔案,例如 d encoder baseline.cfg 然後確定修改 ...