Linux 2 6核心筆記 記憶體管理

2021-08-23 13:58:50 字數 2323 閱讀 3735

4月14日

很多硬體的功能,物盡其用卻未必好過軟實現,linux出於可移植性及其它原因,常常選擇不去過分使用硬體特性。

比如 linux只使用四個segment,分別是__user_cs、__user_ds、__kernel_cs、__kernel_ds,因為paging可以完成segmentation的工作,而且可以完成的更好。而且這樣簡化了很多,統一了邏輯位址和線性位址。

而tss存在每cpu乙個的gdt中,雖然每個process的tss不同,但linux 2.6卻不利用其中的hardware context switch(雖然低版本使用)以乙個far jmp來實現任務轉換,而用一系列的mov指令來實現。這樣做的原因是:

1、可以檢驗ds和es的值,以防惡意的forge。

2、硬轉換和軟轉換所用時間相近,而且硬轉換是無法再優化的,軟轉換則可以。

4月15日

paging也就是將linear位址轉成實體地址的機制。

記憶體被視為一堆4k的小page frame(就像空的格仔),在歸os管的paging機制的苟延殘喘下,彷彿地存放著多於page frame數目的page(資料)。要通過兩層索引(directroy和table)來尋到page,再加offset尋到址。這兩層索引中的entry包含一些標誌表明該page在不在記憶體裡,是否被改寫過,最近是否訪問過,以及讀/寫訪問許可權。

如果page entry裡的page size標誌和cr4的pse標誌設定了的話(extended paging),就是4m一片page frame,這樣就只用directory一層索引了。

從奔騰pro開始,adress針腳非常神奇地從32增加到36,有了乙個叫做pae的機制,它啟用(cr4的pae標誌設定)的時候就是2m一片page frame了。這樣可以定址64gb,遠遠超越了沒啟用前4gb的理論極限(實際極限1gb)。但這樣的定址非常彆扭,因為實體地址雖然因此變成了36位,線性位址仍是32位,要想定址超過4gb,要用cr3去指向不同的pdpt或在31-30bit指定pdpt中entry。不過,更鬱悶的是,這並不能改變process的位址空間4gb的限制,僅僅是核心可以用這麼多記憶體來執行更多的process。

在64位機器上,由於如果只用兩層的話,索引條目會太多,嚴重消耗記憶體,所以只好再加層數,alpha、ia64、ppc64、sh64都是3層(雖然每層bit數不一),x86_64非常神奇地用了4層。

讀的時候,自然有cache hit和cache miss。對於寫操作,cache hit的話,可能有兩種不同的處理方法:write-through(cache和ram都寫)和wirte-back(line換出時寫ram)。linux清空pcd (page cache disable)和pwt (page write-through),永遠啟用cache並使用write-back策略。

哈哈,tlb(translation lookaside buffers )解決了我心中的一大疑問:每次定址(將linear翻譯成physical),都要非常艱辛地查directroy和table,訪問多次ram(你以為這些東西不是放在ram裡啊?!),豈不累死。幸好,我們有tlb,這樣最近翻譯的成果就可以快取在裡面,這樣就省得每次翻譯啦。

4月17日

linux用了四層索引來做paging。這樣既可以通過隱藏掉中間兩層來做無pae的32位paging,又可以隱藏掉pud來支援有pae的3位paging,還可以支援64位的paging。

pte_t     page table

pmd_t   page middle directory

pud_t    page upper directory

pgd_t    page global directory

每個程序的記憶體空間中0到page_offset(0xc0000000,即3g)-1是使用者空間,page_offset到0xffffffff(4g)則是核心空間(只有核心態才能定址)。

啟動的時候,linux問bios記憶體格局如何,保留第1個mb(machine_specific_memory_setup()),然後把自己放在第2個mb開始的地方(從_text到_etext是核心**,從_etext到_edata是初始化了的核心資料)。

在這個過程中:

linux首先建立初始(provisional)頁表(startup_32()),使ram前8m(兩頁)可以用兩種方式定址,用來存放最小的自己(text、data、初始頁表、128k的堆空間)。

接著,linux建立最終頁表。

paging_init()會執行:

cr4 |= pae

__flush_tlb_all()

linux利用cpu有限的指令和行為模式,實現了一系列操縱tlb的函式,應用於不同的情境。

值得一記的是lazy tlb模式,在多cpu系統中,它可以避免無意義的tlb重新整理。

Linux 2 6核心編譯,核心公升級

本文描述了在fc8下公升級linux核心為2.6.25的詳細步驟.1.首先從如下 得到linux 2.6.25.2.然後在 usr src下untar這個包.tar xjfv linux 2.6.25.tar.bz2 3.配置核心 cd usr src linux 2.6.25 make mrpro...

Linux2 6核心啟動分析

我們已知u boot的終極目的是啟動核心,那麼核心啟動的開始必定是u boot傳入的引數。開啟armlinux.c 發現有一行的 為 thekernel 0,bd bi arch number,bd bi boot params 帶入三個引數 第乙個引數是0,第二個引數是機器id,第三個引數是引數所...

Linux 2 6 核心驅動移植

隨著 linux 2.6的發布,由於2.6核心做了教的改動,各個裝置的 驅動程式在不同程度上要進行改寫。為了方便各位linux愛好者我把自己整理的這分文件share出來。該文當列舉了2.6核心同以前版本的絕大多數變化,可惜的是由於時間和精力有限沒有詳細列出各個函式的用法。1 使用新的入口 必須包含 ...