多處理器系統(tǒng)兩種體系結(jié)構(gòu):
-
非一致內(nèi)存訪問(wèn)(Non-Uniform Memory Access,NUMA):這種體系結(jié)構(gòu)下,內(nèi)存被劃分成多個(gè)內(nèi)存節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)由不同的處理器訪問(wèn)。訪問(wèn)一個(gè)內(nèi)存節(jié)點(diǎn)所需的時(shí)間取決于處理器和內(nèi)存節(jié)點(diǎn)之間的距離,因此處理器與內(nèi)存節(jié)點(diǎn)之間的距離會(huì)影響內(nèi)存訪問(wèn)速度。
-
對(duì)稱多處理器(Symmetric Multi-Processor,SMP):這種體系結(jié)構(gòu)是一致內(nèi)存訪問(wèn)(Uniform Memory Access,UMA)的一種形式,所有處理器對(duì)內(nèi)存的訪問(wèn)時(shí)間是相同的,即無(wú)論處理器的位置如何,訪問(wèn)內(nèi)存的開(kāi)銷是相等的。
內(nèi)存模型
Linux內(nèi)核內(nèi)存模型是從處理器的角度看到的物理內(nèi)存分布,內(nèi)核管理不同內(nèi)存模型的方式存在差異。內(nèi)存管理子系統(tǒng)支持以下三種內(nèi)存模型:
-
平坦內(nèi)存(Flat Memory):在這種模型下,內(nèi)存的物理地址空間是連續(xù)的,且沒(méi)有空洞。這是最簡(jiǎn)單的內(nèi)存模型,因?yàn)閷?duì)于物理內(nèi)存的管理而言,只需按順序分配內(nèi)存即可。
-
不連續(xù)內(nèi)存(Discontiguous Memory):在這種模型下,內(nèi)存的物理地址空間存在空洞,但是這種模型可以高效地處理空洞。這是因?yàn)閮?nèi)存管理子系統(tǒng)可以跟蹤哪些物理地址是已經(jīng)被占用,哪些是空閑的,然后在空閑內(nèi)存之間分配新的內(nèi)存。
-
稀疏內(nèi)存(Sparse Memory):在這種模型下,內(nèi)存的物理地址空間也存在空洞,但是如果要支持內(nèi)存熱插拔,只能選擇稀疏內(nèi)存模型。這是因?yàn)樵趦?nèi)存熱插拔時(shí),可能會(huì)出現(xiàn)大量的空洞,如果采用不連續(xù)內(nèi)存模型,那么在進(jìn)行內(nèi)存分配時(shí),需要遍歷整個(gè)物理地址空間,這樣會(huì)造成不必要的開(kāi)銷。而稀疏內(nèi)存模型可以維護(hù)一個(gè)可擴(kuò)展的物理地址空間列表,只需在該列表中分配內(nèi)存即可。
三級(jí)結(jié)構(gòu)
內(nèi)存管理子系統(tǒng)使用節(jié)點(diǎn)、區(qū)域和頁(yè)三級(jí)結(jié)構(gòu)來(lái)描述物理內(nèi)存的管理。
-
節(jié)點(diǎn):節(jié)點(diǎn)是指物理內(nèi)存的邏輯分組單元,通常對(duì)應(yīng)于具有特定特性或位置的一組物理內(nèi)存。每個(gè)節(jié)點(diǎn)包含一個(gè)或多個(gè)區(qū)域,用于管理一定范圍內(nèi)的物理內(nèi)存。
-
區(qū)域:區(qū)域是節(jié)點(diǎn)內(nèi)部的一個(gè)邏輯劃分,用于管理一定范圍內(nèi)的物理內(nèi)存頁(yè)。不同的區(qū)域可能具有不同的特性,例如可回收內(nèi)存、不可回收內(nèi)存等。常見(jiàn)的區(qū)域包括高速緩存區(qū)、低速緩存區(qū)、DMA區(qū)等。
-
頁(yè):頁(yè)是內(nèi)存管理的最小單位,通常是以固定大?。ㄈ?KB)劃分的內(nèi)存塊。操作系統(tǒng)通過(guò)頁(yè)表來(lái)映射虛擬內(nèi)存和物理內(nèi)存之間的對(duì)應(yīng)關(guān)系,實(shí)現(xiàn)內(nèi)存的管理和地址轉(zhuǎn)換。
內(nèi)存節(jié)點(diǎn)(pglist_data)
內(nèi)存節(jié)點(diǎn)分為兩種情況:
-
對(duì)于NUMA(非一致性存儲(chǔ)訪問(wèn))體系的內(nèi)存節(jié)點(diǎn),內(nèi)存節(jié)點(diǎn)根據(jù)處理器和內(nèi)存的距離劃分。在NUMA架構(gòu)中,不同的處理器可能與不同的內(nèi)存區(qū)域相連,因此系統(tǒng)將內(nèi)存劃分為不同的節(jié)點(diǎn),以便更有效地管理和分配內(nèi)存資源。
-
在具有不連續(xù)內(nèi)存的NUMA系統(tǒng)中,內(nèi)存節(jié)點(diǎn)表示比區(qū)域的級(jí)別更高的內(nèi)存區(qū)域,根據(jù)物理地址是否連續(xù)劃分。在這種情況下,每塊物理地址連續(xù)的內(nèi)存被視為一個(gè)內(nèi)存節(jié)點(diǎn)。這種劃分方式可以幫助內(nèi)核更好地管理非連續(xù)內(nèi)存的分配和使用,確保系統(tǒng)能夠有效地利用所有可用的物理內(nèi)存空間。
typedef struct pglist_data {
struct zone node_zones[MAX_NR_ZONES]; // 內(nèi)存區(qū)域數(shù)組
struct zonelist node_zonelists[MAX_ZONELISTS]; // 備用區(qū)域列表
int nr_zones; // 該節(jié)點(diǎn)包含的內(nèi)存區(qū)域數(shù)量
#ifdef CONFIG_FLAT_NODE_MEM_MAP /* means !SPARSEMEM */
struct page *node_mem_map; // 內(nèi)存映射表,存儲(chǔ)每個(gè)物理頁(yè)的信息
#ifdef CONFIG_PAGE_EXTENSION
struct page_ext *node_page_ext; // 頁(yè)的擴(kuò)展屬性
#endif
#endif
unsigned long node_start_pfn; // 該節(jié)點(diǎn)的起始物理頁(yè)號(hào)
unsigned long node_present_pages; // 物理頁(yè)總數(shù),即該節(jié)點(diǎn)上存在的物理頁(yè)數(shù)量
unsigned long node_spanned_pages; // 物理頁(yè)范圍的總長(zhǎng)度,包括空洞,即該節(jié)點(diǎn)的物理頁(yè)范圍總大小
int node_id; // 節(jié)點(diǎn)標(biāo)識(shí)符
...
}
pglist_data
結(jié)構(gòu)體定義了一個(gè)內(nèi)存節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)。
-
node_zones
:內(nèi)存區(qū)域數(shù)組,用于存儲(chǔ)該節(jié)點(diǎn)內(nèi)每個(gè)內(nèi)存區(qū)域的信息。 -
node_zonelists
:備用區(qū)域列表,用于存儲(chǔ)備用的內(nèi)存區(qū)域的信息。 -
nr_zones
:記錄該節(jié)點(diǎn)包含的內(nèi)存區(qū)域的數(shù)量。 -
node_mem_map
:內(nèi)存映射表,用于存儲(chǔ)每個(gè)物理頁(yè)的信息。僅在沒(méi)有使用 SPARSEMEM 的情況下有效。 -
node_page_ext
:頁(yè)的擴(kuò)展屬性,用于存儲(chǔ)與頁(yè)相關(guān)的額外屬性。僅在啟用了 CONFIG_PAGE_EXTENSION 的情況下有效。 -
node_start_pfn
:該節(jié)點(diǎn)的起始物理頁(yè)號(hào)。 -
node_present_pages
:該節(jié)點(diǎn)上存在的物理頁(yè)數(shù)量。 -
node_spanned_pages
:該節(jié)點(diǎn)的物理頁(yè)范圍總大小,包括空洞。 -
node_id
:節(jié)點(diǎn)標(biāo)識(shí)符。
內(nèi)存區(qū)域(zone)
內(nèi)存區(qū)域是將物理內(nèi)存按照不同屬性進(jìn)行劃分的一種方式。每個(gè)內(nèi)存區(qū)域都有一個(gè)唯一的類型標(biāo)識(shí),類型包括 ZONE_DMA、ZONE_DMA32、ZONE_NORMAL、ZONE_HIGHMEM、ZONE_MOVABLE、ZONE_DEVICE 等。
enum zone_type {
// DMA區(qū)域,直接內(nèi)存訪問(wèn)。如果有些設(shè)備不能直接訪問(wèn)所有內(nèi)存,需要使用DMA區(qū)域
#ifdef CONFIG_ZONE_DMA
ZONE_DMA,
#endif
// DMA32區(qū)域64位系統(tǒng),如果既要支持只能直接訪問(wèn)16MB以下的內(nèi)存設(shè)備,又要支持只能直接訪問(wèn)4GB以下內(nèi)存的32設(shè)備,必須使用此DMA32區(qū)域
#ifdef CONFIG_ZONE_DMA32
ZONE_DMA32,
#endif
/*
* Normal addressable memory is in ZONE_NORMAL. DMA operations can be
* performed on pages in ZONE_NORMAL if the DMA devices support
* transfers to all addressable memory.
*/
// 普通區(qū)域:直接映射到內(nèi)核虛擬地址空間的內(nèi)存區(qū)域,又稱為普通區(qū)域
ZONE_NORMAL,
#ifdef CONFIG_HIGHMEM
/*
* A memory area that is only addressable by the kernel through
* mapping portions into its own address space. This is for example
* used by i386 to allow the kernel to address the memory beyond
* 900MB. The kernel will set up special mappings (page
* table entries on i386) for each page that the kernel needs to
* access.
*/
// 高端內(nèi)存區(qū)域:內(nèi)核和用戶地址空間按1:3劃分,內(nèi)核地址空間只有1GB,不能把1GB以上的內(nèi)存直接映射到內(nèi)核地址
ZONE_HIGHMEM,
#endif
// 可移動(dòng)區(qū)域:它是一個(gè)偽內(nèi)存區(qū)域,用來(lái)存放內(nèi)存碎片
ZONE_MOVABLE,
#ifdef CONFIG_ZONE_DEVICE
// 設(shè)備區(qū)域:支持持久內(nèi)存熱插拔增加的內(nèi)存區(qū)域,每個(gè)內(nèi)存區(qū)域有一個(gè)zone結(jié)構(gòu)體來(lái)描述
ZONE_DEVICE,
#endif
__MAX_NR_ZONES
};
這樣整理后的代碼更加清晰易懂,注釋也更容易理解各個(gè)內(nèi)存區(qū)域的作用。
-
ZONE_DMA
:適用于 DMA 的內(nèi)存區(qū)域,長(zhǎng)度受處理器類型的限制。在 IA-32 計(jì)算機(jī)上,限制為 16 MiB。 -
ZONE_DMA32
:適用于可使用 32 位地址字尋址的 DMA 的內(nèi)存區(qū)域。在 64 位系統(tǒng)上,ZONE_DMA 和 ZONE_DMA32 有所不同。在 32 位計(jì)算機(jī)上,ZONE_DMA32 區(qū)域?yàn)榭?,即長(zhǎng)度為 0 MiB。 -
ZONE_NORMAL
:直接映射區(qū)域,標(biāo)記了可直接映射到內(nèi)核段的普通內(nèi)存區(qū)域。這是在所有體系結(jié)構(gòu)上保證都會(huì)存在的唯一內(nèi)存區(qū)域。但是,該地址范圍并不一定對(duì)應(yīng)實(shí)際的物理內(nèi)存,例如在某些系統(tǒng)中,所有內(nèi)存都屬于 ZONE_DMA32 范圍,而 ZONE_NORMAL 區(qū)域?yàn)榭铡?/li> -
ZONE_HIGHMEM
:該內(nèi)存區(qū)域是早期 32 位體系結(jié)構(gòu)的產(chǎn)物,因?yàn)閮?nèi)核和用戶地址空間是 1:3 劃分的,所以不能將內(nèi)核 1GB 以上的內(nèi)存直接映射到內(nèi)核地址空間。在 64 位系統(tǒng)上,由于地址空間非常大,不存在這種問(wèn)題。 -
ZONE_MOVABLE
:可移動(dòng)區(qū)域,是一個(gè)偽內(nèi)存區(qū)域,用于防止內(nèi)存碎片??梢杂糜诜峙錈o(wú)法被移動(dòng)的內(nèi)存對(duì)象的區(qū)域,將該區(qū)域中的頁(yè)框移動(dòng)到另一個(gè)區(qū)域,并釋放原始區(qū)域。 -
ZONE_DEVICE
:持久內(nèi)存熱插拔增加的區(qū)域,用于支持設(shè)備驅(qū)動(dòng)程序動(dòng)態(tài)分配內(nèi)存。
一個(gè)內(nèi)存節(jié)點(diǎn)可能包含多個(gè)內(nèi)存區(qū)域,這些區(qū)域的類型和數(shù)量可以根據(jù)系統(tǒng)的需求進(jìn)行配置。每個(gè)內(nèi)存區(qū)域都有一組特定的操作函數(shù)集合,用于管理該區(qū)域中的頁(yè)框。通過(guò)內(nèi)存區(qū)域的劃分,可以更加有效地管理和利用物理內(nèi)存。
冷熱頁(yè)
-
struct zone
的pageset
成員用于實(shí)現(xiàn)冷熱分配器:在Linux內(nèi)核中,為了提高內(nèi)存管理的效率和性能,使用了冷熱頁(yè)(Cold and Hot Pages)的概念。具體來(lái)說(shuō),在每個(gè)內(nèi)存區(qū)域(zone)中,定義了一個(gè)pageset
結(jié)構(gòu)體,用于管理該區(qū)域中的冷熱頁(yè)。 -
熱頁(yè)指的是已經(jīng)加載到CPU的高速緩存中的頁(yè)面,與內(nèi)存中的其他頁(yè)相比,其數(shù)據(jù)結(jié)構(gòu)可以更快地被訪問(wèn)。冷頁(yè)則指不在CPU高速緩存中的頁(yè)面,當(dāng)需要訪問(wèn)它們時(shí),需要從內(nèi)存中讀取數(shù)據(jù),這會(huì)導(dǎo)致較高的延遲。
-
在多處理器系統(tǒng)中,每個(gè)CPU都有一個(gè)或多個(gè)高速緩存。由于各個(gè)CPU具有獨(dú)立的高速緩存,因此對(duì)冷熱頁(yè)的管理必須是針對(duì)每個(gè)CPU獨(dú)立進(jìn)行的。每個(gè)CPU都有自己的冷熱分配器(
pageset
),用于管理該CPU的熱頁(yè)和冷頁(yè)。這樣可以避免多個(gè)CPU之間相互競(jìng)爭(zhēng)同一份冷熱頁(yè)管理的問(wèn)題,提高了系統(tǒng)的并發(fā)性和性能。
// 每CPU頁(yè)面結(jié)構(gòu)體定義
struct per_cpu_pages {
int count; // 列表中頁(yè)面數(shù)量
int high; // 高水位標(biāo)記,需要清空
int batch; // 伙伴系統(tǒng)添加/移除的塊大小
// 頁(yè)面列表,每個(gè)遷移類型在PCP列表上存儲(chǔ)一個(gè)
struct list_head lists[MIGRATE_PCPTYPES];
};
-
count
記錄了與該列表相關(guān)的頁(yè)面數(shù)量。它表示當(dāng)前列表中的頁(yè)的數(shù)量。 -
high
是一個(gè)水?。╳atermark)。當(dāng)count
的值超過(guò)了high
時(shí),表示列表中的頁(yè)太多了,需要進(jìn)行一些處理。這個(gè)水印可以用來(lái)判斷列表是否過(guò)載。 -
batch
表示每次添加頁(yè)的參考值。在填充CPU高速緩存時(shí),通常不是一次只填充一個(gè)頁(yè)面,而是以塊為單位填充,batch
就是指定每次填充的頁(yè)數(shù)。 -
lists
是一個(gè)數(shù)組,用于存儲(chǔ)不同遷移類型的頁(yè)面列表。每個(gè)遷移類型對(duì)應(yīng)一個(gè)列表,在PCP(per-CPU Page)列表上存儲(chǔ)。
物理頁(yè)(page)
頁(yè)是內(nèi)存管理的最小單位:在內(nèi)存管理中,頁(yè)是內(nèi)存的基本單位,頁(yè)面中的內(nèi)存物理地址是連續(xù)的。在Linux內(nèi)核中,物理頁(yè)被視為內(nèi)存管理的基本單位,即內(nèi)核中的內(nèi)存管理單元MMU將物理頁(yè)作為基本單位進(jìn)行管理。
不同體系結(jié)構(gòu)支持不同的頁(yè)大小:不同的計(jì)算機(jī)體系結(jié)構(gòu)支持不同大小的頁(yè)。例如,32位體系結(jié)構(gòu)通常支持4KB的頁(yè),而64位體系結(jié)構(gòu)通常支持8KB的頁(yè)。另外,像MIPS64架構(gòu)體系可能支持更大的頁(yè),比如16KB的頁(yè)。
每個(gè)物理頁(yè)對(duì)應(yīng)一個(gè)page結(jié)構(gòu)體:在Linux內(nèi)核中,每個(gè)物理頁(yè)都對(duì)應(yīng)一個(gè)稱為頁(yè)描述符(page structure)的數(shù)據(jù)結(jié)構(gòu),用于描述和管理該物理頁(yè)的相關(guān)信息。每個(gè)內(nèi)存節(jié)點(diǎn)的pglist_data
實(shí)例中的成員node_mem_map
指向該內(nèi)存節(jié)點(diǎn)包含的所有物理頁(yè)的頁(yè)描述符組成的數(shù)組。
struct page {
unsigned long flags; // 原子標(biāo)志,有些情況下會(huì)異步更新
union {
struct { // 頁(yè)面緩存和匿名頁(yè)面
struct list_head lru;
// 如果最低位為0,則指向 inode 的 address_space 或?yàn)?NULL
// 如果頁(yè)映射為匿名地址,最低位置位,而且指針指向 anon_vma 對(duì)象
struct address_space *mapping;
pgoff_t index; // 映射中的偏移量
// 用于映射私有、不透明數(shù)據(jù)
// 如果設(shè)置了 PagePrivate,則通常用于 buffer_heads
// 如果設(shè)置了 PageSwapCache,則用于 swp_entry_t
// 如果設(shè)置了 PageBuddy,則用于伙伴系統(tǒng)中的階
unsigned long private;
};
struct { // slab、slob 和 slub
union {
struct list_head slab_list;
struct { // 部分頁(yè)面
struct page *next;
#ifdef CONFIG_64BIT
int pages; // 剩余頁(yè)面數(shù)
int pobjects; // 近似計(jì)數(shù)
#else
short int pages;
short int pobjects;
#endif
};
};
struct kmem_cache *slab_cache; // 非 slob 時(shí)的 kmem_cache 指針
/* 雙字邊界 */
void *freelist; // 第一個(gè)空閑對(duì)象
union {
void *s_mem; // slab 分配器的第一個(gè)對(duì)象
unsigned long counters; // SLUB 計(jì)數(shù)器
struct { // SLUB
unsigned inuse:16;
unsigned objects:15;
unsigned frozen:1;
};
};
};
// 其他字段...
};
};
-
flags
:表示頁(yè)的各種狀態(tài)和屬性的標(biāo)志位。這些標(biāo)志位在某些情況下會(huì)被異步更新。 -
union
:使用聯(lián)合體來(lái)存儲(chǔ)不同類型的頁(yè)的信息。-
對(duì)于頁(yè)面緩存和匿名頁(yè)面(Page cache and anonymous pages):
-
lru
:用于將頁(yè)面鏈接到 LRU(Least Recently Used)鏈表,以進(jìn)行頁(yè)面置換。 -
mapping
:指向 inode 的 address_space 或?yàn)?NULL。如果頁(yè)面映射為匿名地址,則最低位置位且指針指向anon_vma
對(duì)象。 -
index
:表示頁(yè)面在映射中的偏移量。 -
private
:用于映射私有、不透明數(shù)據(jù)。根據(jù)不同的標(biāo)志位,可以用于不同的目的,如PagePrivate
用于buffer_heads
,PageSwapCache
用于swp_entry_t
,PageBuddy
用于伙伴系統(tǒng)中的階。
-
-
對(duì)于 slab、slob 和 slub:
-
slab_list
或next
:用于管理頁(yè)面的鏈表結(jié)構(gòu),對(duì)于 slab 和 slob 分配器,用于鏈接已分配和未分配的頁(yè)面;對(duì)于 slub 分配器,用于鏈接部分頁(yè)面。 -
slab_cache
:對(duì)于 slab 分配器,指向相關(guān)的 kmem_cache 結(jié)構(gòu)體;對(duì)于 slob 分配器和 slub 分配器,該字段不使用。 -
freelist
或s_mem
:對(duì)于 slab 分配器,指向第一個(gè)空閑對(duì)象;對(duì)于 slob 分配器和 slub 分配器,用于存儲(chǔ)其他信息,如計(jì)數(shù)器、使用中的對(duì)象數(shù)量等。
-
-
頁(yè)表
頁(yè)表是操作系統(tǒng)中用于實(shí)現(xiàn)虛擬內(nèi)存到物理內(nèi)存映射的重要數(shù)據(jù)結(jié)構(gòu)。層次化的頁(yè)表結(jié)構(gòu)被設(shè)計(jì)用來(lái)支持對(duì)大地址空間的快速、高效管理。
-
內(nèi)存地址的分解:
根據(jù)四級(jí)頁(yè)表結(jié)構(gòu),虛擬內(nèi)存地址被分解為5部分,其中4個(gè)表項(xiàng)用于選擇頁(yè),1個(gè)索引表示頁(yè)內(nèi)位置。每個(gè)指針末端的幾個(gè)比特位用于指定所選頁(yè)幀內(nèi)部的位置,具體的比特位數(shù)由PAGE_SHIFT指定。PMD_SHIFT指定了頁(yè)內(nèi)偏移量和最后一級(jí)頁(yè)表項(xiàng)所需比特位的總數(shù)。通過(guò)減去PAGE_SHIFT,可以得到最后一級(jí)頁(yè)表項(xiàng)索引所需的比特位數(shù)。類似地,PUD_SHIFT由PMD_SHIFT加上中間層頁(yè)表索引所需的比特位長(zhǎng)度,而PGDIR_SHIFT由PUD_SHIFT加上上層頁(yè)表索引所需的比特位長(zhǎng)度。計(jì)算全局頁(yè)目錄中一項(xiàng)所能尋址的部分地址空間長(zhǎng)度,可以通過(guò)以2為底的對(duì)數(shù)計(jì)算得到PGDIR_SHIFT。 -
頁(yè)表的格式:
內(nèi)核提供了4個(gè)數(shù)據(jù)結(jié)構(gòu)來(lái)表示頁(yè)表項(xiàng)的結(jié)構(gòu):
- pgd_t用于全局頁(yè)目錄項(xiàng)
- pud_t用于上層頁(yè)目錄項(xiàng)
- pmd_t用于中間頁(yè)目錄項(xiàng)
- pte_t用于直接頁(yè)表項(xiàng)
- 特定于PTE的信息:
最后一級(jí)頁(yè)表中的項(xiàng)不僅包含了指向頁(yè)的內(nèi)存位置的指針,還包含了與頁(yè)面相關(guān)的附加信息。每種體系結(jié)構(gòu)都需要提供兩個(gè)東西,以便內(nèi)存管理子系統(tǒng)能夠修改pte_t項(xiàng)中額外的比特位。這兩個(gè)東西分別是保存額外比特位的__pgprot數(shù)據(jù)類型,以及用于修改這些比特位的pte_modify函數(shù)。
通過(guò)以上分析,我們可以更好地理解頁(yè)表的設(shè)計(jì)原理和結(jié)構(gòu),以及各個(gè)級(jí)別的頁(yè)表項(xiàng)在管理地址空間時(shí)的作用和關(guān)聯(lián)。如果您有任何進(jìn)一步的問(wèn)題或需要更多解釋,請(qǐng)隨時(shí)提出。
查詢和設(shè)置內(nèi)存頁(yè)與體系結(jié)構(gòu)相關(guān)狀態(tài)的函數(shù)
-
查詢函數(shù):
-
pte_present()
:檢查給定頁(yè)表項(xiàng)是否存在于內(nèi)存中。 -
pte_write()
:檢查給定頁(yè)表項(xiàng)是否可寫。 -
pte_user()
:檢查給定頁(yè)表項(xiàng)是否為用戶空間可訪問(wèn)。 -
pte_dirty()
:檢查給定頁(yè)表項(xiàng)是否被修改過(guò)。 -
pte_young()
:檢查給定頁(yè)表項(xiàng)是否被訪問(wèn)過(guò)。
-
-
設(shè)置函數(shù):
-
set_pte()
:設(shè)置給定頁(yè)表項(xiàng)的內(nèi)容。 -
set_pte_at()
:在指定地址處設(shè)置頁(yè)表項(xiàng)的內(nèi)容。 -
pte_clear()
:清除給定頁(yè)表項(xiàng)的內(nèi)容。 -
pte_mkwrite()
:將只讀頁(yè)表項(xiàng)轉(zhuǎn)換為可寫。 -
pte_mkdirty()
:標(biāo)記頁(yè)表項(xiàng)已被修改。
-
-
體系結(jié)構(gòu)相關(guān)函數(shù):
-
pgd_index()
:獲取全局頁(yè)目錄項(xiàng)的索引。 -
pmd_offset()
:獲取中間頁(yè)目錄項(xiàng)的指針。 -
pud_offset()
:獲取上層頁(yè)目錄項(xiàng)的指針。 -
pte_offset_kernel()
:獲取內(nèi)核頁(yè)表項(xiàng)的指針。 -
pfn_to_page()
:將物理頁(yè)框號(hào)轉(zhuǎn)換為對(duì)應(yīng)的頁(yè)結(jié)構(gòu)體。
-
創(chuàng)建和操作頁(yè)表項(xiàng)的函數(shù)
-
創(chuàng)建頁(yè)表項(xiàng):
-
pte_alloc()
:分配一個(gè)新的頁(yè)表項(xiàng)。 -
pte_alloc_one()
:分配一個(gè)新的單個(gè)頁(yè)表項(xiàng)。 -
pte_alloc_kernel()
:分配一個(gè)新的內(nèi)核頁(yè)表項(xiàng)。
-
-
釋放頁(yè)表項(xiàng):
-
pte_free()
:釋放一個(gè)頁(yè)表項(xiàng)的內(nèi)存。 -
pte_free_kernel()
:釋放一個(gè)內(nèi)核頁(yè)表項(xiàng)的內(nèi)存。
-
-
操作頁(yè)表項(xiàng):
-
pte_clear()
:清除給定頁(yè)表項(xiàng)的內(nèi)容。 -
pte_val()
:獲取頁(yè)表項(xiàng)的原始值。 -
set_pte()
:設(shè)置指定頁(yè)表項(xiàng)的內(nèi)容。 -
pte_mkclean()
:將頁(yè)表項(xiàng)標(biāo)記為干凈(未修改)。 -
pte_mkdirty()
:將頁(yè)表項(xiàng)標(biāo)記為臟(已修改)。 -
pte_present()
:檢查給定頁(yè)表項(xiàng)是否存在于內(nèi)存中。 -
pte_write()
:檢查給定頁(yè)表項(xiàng)是否可寫。
-
參考:Linux內(nèi)核源碼分析(內(nèi)存調(diào)優(yōu)/文件系統(tǒng)/進(jìn)程管理/設(shè)備驅(qū)動(dòng)/網(wǎng)絡(luò)協(xié)議棧)教程文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-835141.html
Linux內(nèi)核源碼系統(tǒng)性學(xué)習(xí)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-835141.html
>>>
到了這里,關(guān)于【Linux 內(nèi)核源碼分析】物理內(nèi)存組織結(jié)構(gòu)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!