吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux內(nèi)存管理之CPU本地頁(yè)幀緩存

jf_0tjVfeJz ? 來(lái)源:嵌入式ARM和Linux ? 2024-02-20 09:23 ? 次閱讀

0 CPU頁(yè)幀緩存概念

在前一節(jié)中,我們學(xué)習(xí)了buddy伙伴關(guān)系系統(tǒng),它適用于申請(qǐng)連續(xù)的大塊物理內(nèi)存;而有些時(shí)候,經(jīng)常需要申請(qǐng)和釋放單個(gè)頁(yè)幀。但是,如果使用伙伴關(guān)系系統(tǒng),需要查表、進(jìn)行合并等操作,效率不高。為了提高性能,每個(gè)內(nèi)存ZONE區(qū)都提供了一個(gè)per-CPU變量,CPU頁(yè)幀緩存。每個(gè)CPU頁(yè)幀緩存都包含一些預(yù)分配好的頁(yè)幀,滿足本地CPU發(fā)起的單個(gè)頁(yè)幀請(qǐng)求。

實(shí)際上,每個(gè)內(nèi)存ZONE區(qū)和每個(gè)CPU都有2個(gè)緩存:一個(gè)是熱緩存,它存儲(chǔ)頁(yè)幀,其內(nèi)容可能包含在CPU的硬件緩存中;另一個(gè)是冷緩存。

如果內(nèi)核或用戶進(jìn)程在分配后立即寫入頁(yè)幀,那么從熱緩存中獲取頁(yè)幀將有利于系統(tǒng)性能。實(shí)際上,每次訪問(wèn)頁(yè)幀的某個(gè)內(nèi)存位置,都會(huì)導(dǎo)致硬件Cache中替換其它頁(yè)幀的某一行(Cache-line),當(dāng)然,除非硬件Cache已經(jīng)包含剛剛訪問(wèn)的“熱”頁(yè)幀中內(nèi)存位置的一行。

相反,如果要用DMA操作填充頁(yè)幀,則從冷緩存中取頁(yè)幀是很方便的。在這種情況下,不涉及CPU,也不會(huì)修改硬件Cache的任何行。從冷緩存中取頁(yè)幀可以為其他類型的內(nèi)存分配請(qǐng)求保留熱頁(yè)幀。

CPU頁(yè)幀緩存的數(shù)據(jù)結(jié)構(gòu)是per_cpu_pageset類型的數(shù)組,其存儲(chǔ)在內(nèi)存ZONE描述符中的pageset成員中,如下面的代碼所示:

structzone{
/*...*/
structper_cpu_pagesetpageset[NR_CPUS];
/*...*/
}

數(shù)組個(gè)數(shù)與CPU個(gè)數(shù)相關(guān),其中的每個(gè)數(shù)組元素又包含2個(gè)per_cpu_pages描述符成員:一個(gè)是熱緩存;另一個(gè)是冷緩存。而per_cpu_pages數(shù)據(jù)類型的成員如下表所示:

structper_cpu_pages{
intcount;/*緩存中的頁(yè)幀數(shù)量*/
intlow;/*閾值下限,用于緩存補(bǔ)充*/
inthigh;/*閾值上限,需要清空緩存*/
intbatch;/*需從緩存中添加或減少的頁(yè)幀數(shù)*/
structlist_headlist;/*緩存中頁(yè)幀描述符列表,即內(nèi)存頁(yè)列表*/
};

內(nèi)核使用兩個(gè)閾值(low和high)監(jiān)控冷/熱緩存的大小:如果頁(yè)幀數(shù)量低于閾值,則內(nèi)核使用伙伴系統(tǒng)分配一定數(shù)量的單個(gè)頁(yè)幀(batch);否則,頁(yè)幀數(shù)量超過(guò)閾值上限,內(nèi)核將緩存中的頁(yè)幀釋放到伙伴系統(tǒng)中(batch)。batch、low和high的值,具體依賴于內(nèi)存ZONE區(qū)的頁(yè)幀數(shù)量。

1 通過(guò)CPU頁(yè)幀緩存分配頁(yè)幀

buffered_rmqueue()函數(shù)在給定的內(nèi)存ZONE區(qū)中分配頁(yè)幀。它利用CPU頁(yè)幀緩存來(lái)處理單個(gè)頁(yè)幀請(qǐng)求。

Linux v2.6.11內(nèi)核源碼實(shí)現(xiàn)如下所示(文件位置:/mm/page_alloc.c):

staticstructpage*
buffered_rmqueue(structzone*zone,intorder,intgfp_flags)
{
unsignedlongflags;
structpage*page=NULL;
intcold=!!(gfp_flags&__GFP_COLD);

if(order==0){
structper_cpu_pages*pcp;

pcp=&zone->pageset[get_cpu()].pcp[cold];
local_irq_save(flags);
if(pcp->count<=?pcp->low)
pcp->count+=rmqueue_bulk(zone,0,
pcp->batch,&pcp->list);
if(pcp->count){
page=list_entry(pcp->list.next,structpage,lru);
list_del(&page->lru);
pcp->count--;
}
local_irq_restore(flags);
put_cpu();
}

if(page==NULL){
spin_lock_irqsave(&zone->lock,flags);
page=__rmqueue(zone,order);
spin_unlock_irqrestore(&zone->lock,flags);
}

if(page!=NULL){
BUG_ON(bad_range(zone,page));
mod_page_state_zone(zone,pgalloc,1<

輸入參數(shù)分別是內(nèi)存ZONE區(qū)的描述符的地址(zone)、內(nèi)存分配請(qǐng)求大小(2^order)和分配標(biāo)志gfp_flags。如果在gfp_flags中設(shè)置了__GFP_COLD標(biāo)志,則應(yīng)從冷緩存中獲取頁(yè)幀,否則應(yīng)從熱緩存中獲取頁(yè)幀(此標(biāo)志僅對(duì)單個(gè)頁(yè)幀請(qǐng)求有意義)。該函數(shù)基本上執(zhí)行以下操作:

如果order不等于0,則頁(yè)幀緩存不能使用,函數(shù)直接跳轉(zhuǎn)到第4步。

檢查由__GFP_COLD標(biāo)志標(biāo)識(shí)的內(nèi)存ZONE區(qū)域的CPU緩存是否必須被補(bǔ)充(per_cpu_pages的count ≤ low)。在本例中,它執(zhí)行以下子步驟:

重復(fù)調(diào)用__rmqueue()函數(shù),從伙伴系統(tǒng)中分配batch個(gè)頁(yè)幀。

將分配的頁(yè)幀描述符插入到緩存的列表中。

更新count變量(將新分配的頁(yè)幀數(shù)量加上)。

如果count > 0,從緩存列表中取一個(gè)頁(yè)幀,然后跳轉(zhuǎn)到第5步。(CPU頁(yè)幀緩存可能是空的,在第2步的__rmqueue()沒有申請(qǐng)到頁(yè)幀時(shí)就會(huì)發(fā)生)

到這兒,如果內(nèi)存請(qǐng)求沒有被滿足,調(diào)用__rmqueue()申請(qǐng)從伙伴系統(tǒng)中分配所請(qǐng)求頁(yè)幀。

如果內(nèi)存請(qǐng)求被滿足,初始化該頁(yè)幀(第1個(gè))的頁(yè)描述符:清除某些標(biāo)志、設(shè)置private為0,設(shè)置頁(yè)幀引用計(jì)數(shù)器為1。另外,如果設(shè)置了__GPF_ZERO,將申請(qǐng)的內(nèi)存清零。

返回頁(yè)幀(第1個(gè))的描述符,失敗返回NULL。

2 通過(guò)CPU頁(yè)幀緩存釋放頁(yè)幀

從CPU頁(yè)幀緩存中釋放頁(yè)幀,使用free_hot_page()和free_cold_page()函數(shù)。它們都是free_hot_cold_page()的封裝函數(shù),如下所示(文件位置:/mm/page_alloc.c):

staticvoidfastcallfree_hot_cold_page(structpage*page,intcold)
{
structzone*zone=page_zone(page);
structper_cpu_pages*pcp;
unsignedlongflags;

arch_free_page(page,0);

kernel_map_pages(page,1,0);
inc_page_state(pgfree);
if(PageAnon(page))
page->mapping=NULL;
free_pages_check(__FUNCTION__,page);
pcp=&zone->pageset[get_cpu()].pcp[cold];
local_irq_save(flags);
if(pcp->count>=pcp->high)
pcp->count-=free_pages_bulk(zone,pcp->batch,&pcp->list,0);
list_add(&page->lru,&pcp->list);
pcp->count++;
local_irq_restore(flags);
put_cpu();
}

free_hot_cold_page()接受的參數(shù)是待釋放頁(yè)幀的描述符地址page,表示熱緩存還是冷緩存的標(biāo)志cold。

執(zhí)行的步驟如下:

根據(jù)頁(yè)幀,獲取page->flags標(biāo)志。

根據(jù)cold標(biāo)志獲取對(duì)應(yīng)頁(yè)幀緩存的描述符per_cpu_pages地址。

檢查緩存是否不足:如果count ≥ high,調(diào)用free_pages_bulk()函數(shù)。該函數(shù)會(huì)重復(fù)調(diào)用__free_pages_bulk()函數(shù)釋放指定的頁(yè)幀到伙伴系統(tǒng)中。

將該頁(yè)幀添加到緩存列表中,增加count計(jì)數(shù)。

應(yīng)該注意的是,在Linux v2.6內(nèi)核中,沒有任何頁(yè)幀被釋放到冷緩存中:內(nèi)核總是假設(shè)釋放的頁(yè)幀相對(duì)于硬件緩存來(lái)說(shuō)是熱的。當(dāng)然,這并不意味著冷緩存是空的:當(dāng)達(dá)到低閾值時(shí),緩存由buffered_rmqueue()補(bǔ)充。

3 移除__GFP_COLD

雖然我們前邊分析了基于冷熱緩存的CPU頁(yè)幀緩存,但是,從v4.14版本以后的內(nèi)核中已經(jīng)移除,參考patch。Patches 1-4是與移除冷緩存最相關(guān)的部分;Patches 5-8是可選的,因?yàn)樗鼈兌际莿h除無(wú)用但也不影響性能的代碼。

free_hot_cold_page的大多數(shù)調(diào)用者用戶都聲稱被釋放的頁(yè)是熱緩存的。唯一的例外是頁(yè)回收代碼,因?yàn)樵诓痪玫膶?lái)可能會(huì)釋放足夠多的頁(yè),因此CPU的本地頁(yè)幀緩存列表將被回收,熱緩存信息將丟失。由于沒有人真正關(guān)心被釋放到分配器的頁(yè)的熱信息,所以省略該參數(shù)即可。




審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 計(jì)數(shù)器
    +關(guān)注

    關(guān)注

    32

    文章

    2261

    瀏覽量

    94994
  • Cache
    +關(guān)注

    關(guān)注

    0

    文章

    129

    瀏覽量

    28435
  • LINUX內(nèi)核
    +關(guān)注

    關(guān)注

    1

    文章

    316

    瀏覽量

    21744

原文標(biāo)題:Linux內(nèi)核8.5-內(nèi)存管理之CPU本地頁(yè)幀緩存

文章出處:【微信號(hào):嵌入式ARM和Linux,微信公眾號(hào):嵌入式ARM和Linux】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Linux內(nèi)存管理是什么,Linux內(nèi)存管理詳解

    Linux內(nèi)存管理 Linux內(nèi)存管理是一個(gè)非常復(fù)雜的過(guò)程,主要分成兩個(gè)大的部分:內(nèi)核的
    的頭像 發(fā)表于 05-11 17:54 ?6158次閱讀
    <b class='flag-5'>Linux</b>的<b class='flag-5'>內(nèi)存</b><b class='flag-5'>管理</b>是什么,<b class='flag-5'>Linux</b>的<b class='flag-5'>內(nèi)存</b><b class='flag-5'>管理</b>詳解

    Linux內(nèi)存管理頁(yè)面回收

    請(qǐng)求調(diào)頁(yè)機(jī)制,只要用戶態(tài)進(jìn)程繼續(xù)執(zhí)行,他們就能獲得頁(yè)框,然而,請(qǐng)求調(diào)頁(yè)沒有辦法強(qiáng)制進(jìn)程釋放不再使用的頁(yè)框。因此,遲早所有空閑內(nèi)存將被分配給進(jìn)
    發(fā)表于 05-19 14:09 ?1128次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)存</b><b class='flag-5'>管理</b><b class='flag-5'>之</b>頁(yè)面回收

    關(guān)于Linux內(nèi)存管理的詳細(xì)介紹

    Linux內(nèi)存管理是指對(duì)系統(tǒng)內(nèi)存的分配、釋放、映射、管理、交換、壓縮等一系列操作的管理。在
    發(fā)表于 03-06 09:28 ?1091次閱讀

    Linux內(nèi)核內(nèi)存管理ZONE內(nèi)存分配器

    內(nèi)核中使用ZONE分配器滿足內(nèi)存分配請(qǐng)求。該分配器必須具有足夠的空閑頁(yè),以便滿足各種內(nèi)存大小請(qǐng)求。
    的頭像 發(fā)表于 02-21 09:29 ?950次閱讀

    Linux內(nèi)核內(nèi)存管理之內(nèi)核非連續(xù)物理內(nèi)存分配

    我們已經(jīng)知道,最好將虛擬地址映射到連續(xù)頁(yè),從而更好地利用緩存并實(shí)現(xiàn)更低的平均內(nèi)存訪問(wèn)時(shí)間。然而,如果對(duì)內(nèi)存區(qū)域的請(qǐng)求并不頻繁,那么考慮基于
    的頭像 發(fā)表于 02-23 09:44 ?1079次閱讀
    <b class='flag-5'>Linux</b>內(nèi)核<b class='flag-5'>內(nèi)存</b><b class='flag-5'>管理</b>之內(nèi)核非連續(xù)物理<b class='flag-5'>內(nèi)存</b>分配

    HVM的緩存控制與內(nèi)存管理

    控制的虛擬指令 下圖列出了HVM緩存控制的虛擬指令: 內(nèi)存管理概述 HVM映射虛擬地址0x0000_0000至0xfeff_ffff置于一個(gè)32位的邏輯地址空間,既可以使用一系列的轉(zhuǎn)換或者1或2級(jí)別
    發(fā)表于 09-20 10:19

    Linux內(nèi)存管理導(dǎo)讀

    Linux 內(nèi)存管理導(dǎo)讀 :1. 存儲(chǔ)層次結(jié)構(gòu)和 x86存儲(chǔ)管理硬件(MMU) 1.1 存儲(chǔ)層次 高速緩存(cache) 主存(main m
    發(fā)表于 11-03 22:32 ?39次下載

    渲染中的緩存和深度緩存

    渲染涉及大量的緩存,這里緩存只是一個(gè)簡(jiǎn)單的存有像素?cái)?shù)據(jù)的矩形內(nèi)存塊,最重要緩存緩存和深度
    的頭像 發(fā)表于 05-14 11:44 ?6459次閱讀
    渲染中的<b class='flag-5'>幀</b><b class='flag-5'>緩存</b>和深度<b class='flag-5'>緩存</b>

    Linux性能及調(diào)優(yōu)指南:內(nèi)存架構(gòu)

    Linux管理swap空間也非常有效率。swap空間被使用時(shí)并不意味著出現(xiàn)內(nèi)存的瓶頸,它恰恰證明了Linux管理系統(tǒng)資源如何的有效。詳見“
    發(fā)表于 04-02 14:32 ?382次閱讀

    CPU緩存的作用及原理有哪些

    CPU緩存是位于CPU內(nèi)存之間的臨時(shí)存儲(chǔ)器,它的容量比內(nèi)存小很多,但交換速度比內(nèi)存要快很多。
    的頭像 發(fā)表于 08-27 15:58 ?1.1w次閱讀

    關(guān)于CPU緩存的作用

    CPU沒有存儲(chǔ)功能,那么緩存到底是干什么的?CPU緩存是用于減少處理器訪問(wèn)內(nèi)存所需平均時(shí)間的部件,作用類似于
    的頭像 發(fā)表于 03-30 10:58 ?4604次閱讀
    關(guān)于<b class='flag-5'>CPU</b><b class='flag-5'>緩存</b>的作用

    如何在 Linux 上查看本地 DNS 緩存

    ? 刷新本地 DNS 緩存可以解決 HTTP 錯(cuò)誤并保護(hù)您免受 DNS 欺騙。以下是在 Linux 上執(zhí)行此操作的方法。 當(dāng)您使用域名訪問(wèn)網(wǎng)站時(shí),您的系統(tǒng)會(huì)向 DNS 服務(wù)器發(fā)送請(qǐng)求以獲取該域
    的頭像 發(fā)表于 06-26 10:52 ?3423次閱讀
    如何在 <b class='flag-5'>Linux</b> 上查看<b class='flag-5'>本地</b> DNS <b class='flag-5'>緩存</b>

    Linux 內(nèi)存管理總結(jié)

    緩存、交換分區(qū)等。Linux內(nèi)存管理的目標(biāo)是最大限度地利用可用內(nèi)存,同時(shí)保證系統(tǒng)的穩(wěn)定和可靠性。 1.1 什么是
    的頭像 發(fā)表于 11-10 14:58 ?593次閱讀
    <b class='flag-5'>Linux</b> <b class='flag-5'>內(nèi)存</b><b class='flag-5'>管理</b>總結(jié)

    什么是CPU緩存?它有哪些作用?

    CPU緩存(Cache Memory)是計(jì)算機(jī)系統(tǒng)中一個(gè)至關(guān)重要的組成部分,它位于CPU內(nèi)存之間,作為兩者之間的臨時(shí)存儲(chǔ)器。CPU
    的頭像 發(fā)表于 08-22 14:54 ?3754次閱讀

    緩存美——如何選擇合適的本地緩存

    Guava cache是Google開發(fā)的Guava工具包中一套完善的JVM本地緩存框架,底層實(shí)現(xiàn)的數(shù)據(jù)結(jié)構(gòu)類似于ConcurrentHashMap,但是進(jìn)行了更多的能力拓展,包括緩存過(guò)期時(shí)間設(shè)置、
    的頭像 發(fā)表于 11-17 14:24 ?417次閱讀
    <b class='flag-5'>緩存</b><b class='flag-5'>之</b>美——如何選擇合適的<b class='flag-5'>本地</b><b class='flag-5'>緩存</b>?
    做生意门店风水知识| 海林市| 15人百家乐桌布| 迪威百家乐官网娱乐| 盛大百家乐的玩法技巧和规则| 168棋牌游戏| 百家乐有多少种游戏| 迪威百家乐官网娱乐| 威尼斯人娱乐城演唱会| 娱乐百家乐官网可以代理吗| 博彩网58娱乐城| 百家乐稳赢投资法| 蓝盾百家乐官网具体玩法| 注册娱乐城送体验金| 大佬百家乐官网娱乐城| 文化| 大发888娱乐平台下载| 百家乐有多少局| 百家乐官网怎样赢| 奔驰百家乐官网可信吗| 大发888非法吗| 百家乐是不是有技巧| 御金百家乐官网娱乐城| 菲律宾新利国际| 大发百家乐的玩法技巧和规则| 足球百家乐官网系统| 百家乐官网娱乐注册就送| bet365指数| 真人百家乐赌场娱乐网规则| 至尊百家乐官网网| 全州县| 大发888游戏平台hgx2dafa888gw| 游戏厅百家乐技巧| 百家乐官网专业豪华版| 廉江市| 云鼎娱乐场送彩金| 回力百家乐的玩法技巧和规则 | 百家乐官网赌博程序| 建平县| 网上娱乐城排名| 百家乐游戏筹码|