色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux中匿名頁的訪問分析

Linux閱碼場 ? 來源:Linux內核遠航者 ? 作者:Linux內核遠航者 ? 2021-10-12 17:52 ? 次閱讀

Linux有后備文件支持的頁稱為文件頁,如屬于進程的代碼段、數據段的頁,內存回收的時候這些頁面只需要做臟頁的同步即可(干凈的頁面可以直接丟棄掉)。反之為匿名頁,如進程的堆棧使用的頁,內存回收的時候這些頁面不能簡單的丟棄掉,需要交換到交換分區或交換文件。本文中,主要分析匿名頁的訪問將發生哪些可能顛覆我們認知的"化學反應"。

1.實例代碼

首先以一個簡單的示例代碼來說明:

#include
#include
#include
#include
#include

#defineMAP_SIZE(100*1024*1024)

intmain(intargc,char*argv[])
{
char*p;
charval;
inti;

puts("beforemmapok,pleaceexec'free-m'!");
sleep(5);


//mmap

p=mmap(NULL,MAP_SIZE,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
if(p==NULL){
perror("failtomalloc");
return-1;
}
puts("aftermmapok,pleaceexec'free-m'!");
sleep(5);


//read
for(i=0;i"readok,pleaceexec'free-m'!");
sleep(5);

#if1
//write
memset(p,0x55,MAP_SIZE);
puts("writeok,pleaceexec'free-m'!");
#endif
//sleep
pause();

return0;
}

代碼非常簡單:首先通過mmap分配100M的私有可讀可寫匿名頁面,然后進行讀寫訪問,分別在提示的時候在另外一個窗口執行free -m命令查看輸出結果。

程序執行結果如下:

$./anon_rw_demo
beforemmapok,pleaceexec'free-m'!
aftermmapok,pleaceexec'free-m'!
readok,pleaceexec'free-m'!
writeok,pleaceexec'free-m'!


命令執行結果如下:

$free-m
總計已用空閑共享緩沖/緩存可用
內存: 15729  8286  1945  895  5497  6220
交換: 16290 1599  14691
$free-m
總計已用空閑共享緩沖/緩存可用
內存: 15729  8286  1945  895  5497  6220
交換: 16290 1599  14691
$free-m
總計已用空閑共享緩沖/緩存可用
內存: 15729  8286  1945  895  5497  6220
交換: 16290 1599  14691
$free-m
總計已用空閑共享緩沖/緩存可用
內存: 15729  8383  1848  895  5497  6123
交換: 16290 1599  14691

可以看到:

第一次提示執行free命令的時候,我們還沒有開始通過mmap分配內存,此時free命令輸出作為參考。

第二次提示執行free命令的時候,我們已經通過mmap分配了100M的內存,此時發現free命令輸出內存消耗基本沒有變化。

第三次提示執行free命令的時候,我們對于分配的匿名頁面進行了讀操作,此時發現free命令輸出內存消耗頁基本沒有變化,這基本上會顛覆我們的認知

第四次提示執行free命令的時候,我們對于分配的匿名頁面進行了寫操作,此時發現free命令輸出內存消耗大概為100M。

2.內核原理

下面我們從Linux內核的層面來解析發生以上神奇現象的原理。

2.1 mmap的內存消耗

mmap申請匿名頁的時候,只是申請了虛擬內存(通過vm_area_struct結構來描述,如描述虛擬內存區域的地址范圍、訪問權限等,以下簡稱vma),實際的物理內存并沒有申請(除了用于管理虛擬內存區域的vma等結構內存的申請),當前虛擬內存和物理內存并沒有建立頁表映射關系,而真正的申請的匿名頁所對應的物理頁在實際訪問的時候按需分配獲得,所以此時我們看不到內存的消耗情況。

2.2 第一次讀匿名頁的內存消耗

通過mmap申請完虛擬內存之后,進程就可以按照之前申請vma的訪問權限進行訪問,第一發生讀訪問,這個時候由于虛擬內存和物理內存并沒有建立頁表映射關系,通過虛擬地址并不能查找到物理內存,所以會發生處理器的異常,最終分析是因為數據訪問異常導致,就由處理器架構相關的代碼進入了我們通用的缺頁異常處理例程中。

缺頁異常調用鏈如下:

"mm/memory.c"

處理器架構相關異常處理代碼
->handle_mm_fault
->__handle_mm_fault
->handle_pte_fault
->if(!vmf->pte){-------------------1
if(vma_is_anonymous(vmf->vma))-------------------2
returndo_anonymous_page(vmf);-------------------3

缺頁異常進入handle_pte_fault后,在1標簽代碼處,來判斷訪問的虛擬內存頁的頁表項是否為空,為空說明這個這個虛擬頁沒有和物理頁建立映射關系。然后在2標簽代碼處判斷是否為匿名頁缺頁異常(實際上是判斷是否為私有的匿名頁,當前當前示例代碼場景申請的為私有匿名頁面)。在3標簽代碼處,進行真正的私有匿名頁缺頁異常處理。

下面主要看下第一次讀匿名頁的處理:

do_anonymous_page
->pte_alloc(vma->vm_mm,vmf->pmd)-------------------1
->/*Usethezero-pageforreads*/
if(!(vmf->flags&FAULT_FLAG_WRITE)&&-------------------2
!mm_forbids_zeropage(vma->vm_mm)){-------------------3
entry=pte_mkspecial(pfn_pte(my_zero_pfn(vmf->address),
vma->vm_page_prot));-------------------4
vmf->pte=pte_offset_map_lock(vma->vm_mm,vmf->pmd,
vmf->address,&vmf->ptl);-------------------5

...
gotosetpte;
}
->page=alloc_zeroed_user_highpage_movable(vma,vmf->address);-------------------6
->entry=mk_pte(page,vma->vm_page_prot);-------------------7
entry=pte_sw_mkyoung(entry);-------------------8
if(vma->vm_flags&VM_WRITE)
entry=pte_mkwrite(pte_mkdirty(entry));-------------------9

vmf->pte=pte_offset_map_lock(vma->vm_mm,vmf->pmd,vmf->address,
&vmf->ptl);-------------------10

->set_pte_at(vma->vm_mm,vmf->address,vmf->pte,entry);-------------------11

1標簽處:判斷虛擬地址對應的pmd表項是否為空,為空來分配直接頁表設置到pmd表項中。

2標簽處:判斷是否是進行讀訪問。

3標簽處:判斷是否沒有禁止0頁。

4標簽處:就是對于沒有禁止0頁的匿名頁讀訪問設置頁表,這里通過0頁的頁幀號和mmap映射時指定的訪問權限組合頁表項的值。

5標簽處:通過發生缺頁的虛擬地址來計算出頁表項的地址保存在 vmf->pte。

最11標簽處:將4標簽初組合出的頁表項的值寫入到5標簽初計算出的頁表項中。

以上分析可知:對于私有的匿名頁,第一次讀訪問的時候都會發生缺頁異常,然后通過頁表映射0頁,這個0頁沒有什么特殊之處,只不過它是在系統啟動過程中初始化好的一塊內容全為0的頁面,這樣做可以為進程分配了內存只進行讀訪問節省大量物理內存。

2.3 第一次寫匿名頁的內存消耗

大家可以將示例代碼中,讀訪問屏蔽掉只進行寫訪問,觀察內存消耗。

這個時候發生缺頁異常時,不會在走2 3 4 5 便簽處代碼,而在6處分配了一個物理頁面,在7 8 9組合頁表項的值, 10處計算出頁表項的地址,最后把組合的值設置到頁表項中。

需要注意第9處,如果是寫訪問會設置頁表項的可寫標志位

以上分析可知:對于私有的匿名頁,第一次寫訪問的時候都會發生缺頁異常,會真正分配一個物理頁面,然后將虛擬頁面通過頁面映射到物理頁面,所以我們能觀察到寫之后發生了大量內存消耗。

2.4 第一次讀然后寫匿名頁的內存消耗

這種場景就是示例代碼中所做的實驗,可以看到讀的時候基本上沒有內存消耗,寫的時候發生了大量內存消耗。

關于第一次讀,上面已經做過解釋,下面主要看讀完之后的頁面發生寫訪問的情況。

2.4.1 從mmap說起

實際上,對于一個私有的內存映射,在mmap的時候為頁表映射準備訪問權限的時候并不是給予所有的權限,而是把可寫屬性去掉了。

我們可以從源代碼找到答案:

"mm/mmap.c"

do_mmap
->mmap_region
->vma_set_page_prot(vma)
->vm_page_prot=vm_pgprot_modify(vma->vm_page_prot,vm_flags);---------1
->pgprot_modify(oldprot,vm_get_page_prot(vm_flags))
->WRITE_ONCE(vma->vm_page_prot,vm_page_prot);---------------2


/*descriptionofeffectsofmappingtypeandprotincurrentimplementation.
*thisisduetothelimitedx86pageprotectionhardware.Theexpected
*behaviorisinparens:
*
*map_typeprot
*PROT_NONEPROT_READPROT_WRITEPROT_EXEC
*MAP_SHAREDr:(no)nor:(yes)yesr:(no)yesr:(no)yes
*w:(no)now:(no)now:(yes)yesw:(no)no
*x:(no)nox:(no)yesx:(no)yesx:(yes)yes
*
*MAP_PRIVATEr:(no)nor:(yes)yesr:(no)yesr:(no)yes
*w:(no)now:(no)now:(copy)copyw:(no)no
*x:(no)nox:(no)yesx:(no)yesx:(yes)yes
*/
->vm_get_page_prot
pgprot_tprotection_map[16]__ro_after_init={
__P000,__P001,__P010,__P011,__P100,__P101,__P110,__P111,
__S000,__S001,__S010,__S011,__S100,__S101,__S110,__S111
};


對于__Pxxx, 最后一個x表示vma屬性是否可讀,倒數第二個x表示vma屬性是否可寫,P后面的x表示是否可執行。

1標簽處根據mmap傳遞的訪問權限來構造最終的訪問權限標識。

2標簽處將構造好的訪問權限標識記錄到vma->vm_page_prot中,供缺頁異常設置頁表使用。

注釋中已經做了詳細的解釋,具體頁表屬性如何表示由各自的處理器架構相關代碼來做(eg: 對于x86架構 #define __P111 PAGE_COPY_EXEC),我們只需要知道:無論我們想讓vma具備那些屬性組合,都會屏蔽掉寫屬性,具體可以查看相關的處理器架構實現。

所以,再次回到缺頁異常處理代碼中。在2.2小節的4標簽處,使用mmap設置好的頁表訪問權限設置頁表屬性,當前場景我們知道,mmap中指定為私有的可讀可寫屬性,而頁表中只是設置為了只讀屬性

2.4.2 寫時復制的觸發

讀訪問將虛擬頁以只讀的方式映射到了0頁,當再次發生寫操作時,就會再次觸數據訪問異常,最終進入缺頁異常處理例程中。

下面給出調用鏈:

"mm/memory.c"

handle_pte_fault
->if(vmf->flags&FAULT_FLAG_WRITE){-----------1
if(!pte_write(entry))-----------2
returndo_wp_page(vmf);-----------3

可以看到最終也是在handle_pte_fault中處理:在1標簽處判斷是否為寫訪問。在2標簽處判斷頁表項的屬性是否是只讀。在3標簽處進行實際的寫時復制處理。

以上分析可知:發生寫訪問操作時,如果vma可寫,但是頁表屬性標識不可寫(只讀),會發生寫時復制缺頁異常,對于當前場景的0頁的寫訪問就是如此,在do_wp_page中會重新分配物理頁面映射到虛擬頁面,然后頁表設置為可寫屬性,就完成了缺頁處理。

3.總結

1)mmap分配私有匿名內存時,會設置vma的vm_page_prot成員,去除掉頁表的寫訪問標識。

2)第一次讀匿名頁時,對于可讀可寫的vma,虛擬頁會以只讀的方式映射到0頁。

3)第一次寫匿名頁時,對于可讀可寫的vma,會申請物理頁面,虛擬頁以可讀可寫的方式映射到此物理頁。

4)第一次讀匿名頁后,然后寫匿名頁,先只讀方式映射到0頁,然后發生寫時復制,分配物理頁,虛擬頁以可讀可寫的方式映射到此物理頁。

可以發現,訪問匿名頁面時發生的“化學反應”并不是那么的簡單,其中會涉及mmap的映射原則,0頁的映射,匿名頁面的處理,寫時復制的處理等等,而且讀寫順序不一樣,產生的結果也會不一樣,大家可以結合內核源代碼進行分析,希望對大家理解匿名頁缺頁異常有所幫助。

責任編輯:haq


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11296

    瀏覽量

    209348
  • 代碼
    +關注

    關注

    30

    文章

    4780

    瀏覽量

    68530

原文標題:3.總結

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Linux lsof命令的基本用法

    linux 系統,一切皆文件。通過文件不僅僅可以訪問常規數據,還可以訪問網絡連接和硬件。所以 lsof 命令不僅可以查看進程打開的文件、目錄,還可以查看進程監聽的端口等 sock
    的頭像 發表于 10-23 11:52 ?242次閱讀
    <b class='flag-5'>Linux</b> lsof命令的基本用法

    存儲器訪問速度最快的是什么

    在探討存儲器訪問速度最快的是哪一種時,我們首先需要了解計算機存儲系統的層次結構以及各類存儲器的特性和功能。計算機存儲系統通常包括多個層次的存儲器,從速度最快、容量最小的寄存器開始,到速度較慢、容量較大的外存儲器結束。這些存儲器在訪問
    的頭像 發表于 10-12 17:01 ?1802次閱讀

    匿名瀏覽到數據安全:代理IP用戶心聲全記錄

    匿名瀏覽到數據安全,代理IP技術在現代網絡環境扮演著重要角色。以下是代理IP用戶心聲的全記錄,涵蓋了其應用、優勢、挑戰及用戶心聲。
    的頭像 發表于 09-30 08:59 ?195次閱讀

    動態代理IP的匿名性和透明度,為主要考慮關鍵!

    動態代理IP的匿名性和透明度是用戶選擇代理服務時需要考慮的關鍵因素。根據用戶的需求和場景,可以選擇不同匿名級別和透明度的代理服務來平衡隱私保護和網絡訪問的需求。
    的頭像 發表于 09-20 07:36 ?273次閱讀
    動態代理IP的<b class='flag-5'>匿名</b>性和透明度,為主要考慮關鍵!

    Linux內核表映射的基礎知識

    大家在看內核代碼時會經常看的以上術語,但在ARM的芯片手冊并沒有用到這些術語,而是使用L1,L2,L3表這種術語。
    的頭像 發表于 08-07 15:53 ?875次閱讀
    <b class='flag-5'>Linux</b>內核<b class='flag-5'>中</b><b class='flag-5'>頁</b>表映射的基礎知識

    詳解Linux的權限控制

    本章將和大家分享Linux的權限控制。廢話不多說,下面我們直接進入主題。
    的頭像 發表于 08-05 15:32 ?566次閱讀
    詳解<b class='flag-5'>Linux</b><b class='flag-5'>中</b>的權限控制

    云服務器linux搭建ftp服務訪問不了怎么解決?

    如果你在云服務器linux上搭建了FTP服務但無法訪問,這可能是由于幾種原因引起的。以下是一些常見問題和解決方法: 1、防火墻配置:確保防火墻允許FTP流量通過。FTP服務器通常使用端口21(控制
    的頭像 發表于 04-18 17:23 ?1497次閱讀

    loongarch是如何區分大和基本頁的?

    在開發loongarch架構的操作系統的時候,我遇到了這樣的問題:我不知道硬件是如何區分大和基本頁的。 如圖,關于基本頁和大的格式在手冊是這樣的敘述的: 即便手冊闡述了基本頁和
    發表于 03-30 12:05

    Linux內核內存管理之內核非連續物理內存分配

    我們已經知道,最好將虛擬地址映射到連續幀,從而更好地利用緩存并實現更低的平均內存訪問時間。然而,如果對內存區域的請求并不頻繁,那么考慮基于通過連續線性地址訪問非連續幀的分配方案是有
    的頭像 發表于 02-23 09:44 ?947次閱讀
    <b class='flag-5'>Linux</b>內核內存管理之內核非連續物理內存分配

    Linux內存管理之CPU本地幀緩存

    在前一節,我們學習了buddy伙伴關系系統,它適用于申請連續的大塊物理內存;而有些時候,經常需要申請和釋放單個幀。
    的頭像 發表于 02-20 09:23 ?491次閱讀

    鴻蒙ArkUI開發-實現增刪Tab

    本文以瀏覽器增加或刪除簽為例,實現Tabs簽的增刪功能。
    的頭像 發表于 01-29 18:43 ?1578次閱讀
    鴻蒙ArkUI開發-實現增刪Tab<b class='flag-5'>頁</b>簽

    如何通過WebDAV服務器訪問NAS

    WebDAV的客戶端程序(如WinSCP、RaiDrive、Mac OS Finder、Linux 資源管理器)訪問TNAS設備。 接下來為大家分享如何通過WebDAV服務器訪問鐵威馬NAS: 1、使用擁有
    的頭像 發表于 01-16 15:30 ?1041次閱讀
    如何通過WebDAV服務器<b class='flag-5'>訪問</b>NAS

    如何解決C語言中的“訪問權限沖突”異常?C語言引發異常原因分析

    如何解決C語言中的“訪問權限沖突”異常?C語言引發異常原因分析? 在C語言中,訪問權限沖突異常通常是由于嘗試訪問未授權的變量、函數或其他數據結構而引起的。這種異常是編程中常見的錯誤之一
    的頭像 發表于 01-12 16:03 ?5644次閱讀

    如何解決Linux系統的網絡連接問題?

    如何解決Linux系統的網絡連接問題? Linux系統的網絡連接問題是常見的技術難題之一,通常涉及在Linux上配置網絡接口、解決網絡故
    的頭像 發表于 01-12 15:17 ?987次閱讀

    Linux常用命令自學手冊》+一本手邊linux速查字典

    占用的頁數不多,2-3,有些就1,可以說精練到都是精華了,從內容上看,有語法格式,常用參數,參考示例,有助于快速學習,如果需要深入了解,則可以看看《linux命令速查手冊》,它一般一個命令會有3
    發表于 12-26 08:46
    主站蜘蛛池模板: 福利一区国产| 依人青青青在线观看| 日本久久黄色| 欧美人与动牲交A免费| 麻豆COMCN| 久久青草免费线观最新| 精品一区二区三区四区五区六区| 国产色精品久久人妻无码看片软件| 耻辱诊察室1一4集动漫在线观看| sao虎影院桃红视频在线观看| japanese色系free日本| 99久久免费热在线精品| beeg日本老师| YY6080A旧里番在线观看| 爱穿丝袜的麻麻3d漫画acg| xx69美国| 儿媳妇完整版视频播放免费观看| 纯肉高H啪短文合集| 国产成人精品自拍| 国产精品手机在线视频| 国语自产拍在线视频普通话| 天天躁躁水汪汪人碰人| 三叶草未满十八岁| 外国三级片名| 亚洲高清在线mv| 亚洲野狼综合网站| 2019一級特黃色毛片免費看| 99久久做夜夜爱天天做精品| https黄视| 国产精品igao视频网网址| 幻女FREE性俄罗斯学生| 久久久久嫩草影院精品| 免费看毛片网| 日本亚洲电影| 亚洲国产精品综合久久一线| 在教室伦流澡到高潮HNP视频| 99re这里只有精品视频| 国产 高清 无码 中文| 精品国产品国语在线不卡丶| 男女啪啪抽搐呻吟高潮动态图 | 97无码欧美熟妇人妻蜜|