国产一区二区精品-国产一区二区精品久-国产一区二区精品久久-国产一区二区精品久久91-免费毛片播放-免费毛片基地

千鋒教育-做有情懷、有良心、有品質(zhì)的職業(yè)教育機(jī)構(gòu)

手機(jī)站
千鋒教育

千鋒學(xué)習(xí)站 | 隨時(shí)隨地免費(fèi)學(xué)

千鋒教育

掃一掃進(jìn)入千鋒手機(jī)站

領(lǐng)取全套視頻
千鋒教育

關(guān)注千鋒學(xué)習(xí)站小程序
隨時(shí)隨地免費(fèi)學(xué)習(xí)課程

當(dāng)前位置:首頁(yè)  >  技術(shù)干貨  > Linux內(nèi)存管理

Linux內(nèi)存管理

來(lái)源:千鋒教育
發(fā)布人:syq
時(shí)間: 2022-10-27 10:57:40 1666839460

  一、物理內(nèi)存的組織形式:

  由于物理內(nèi)存是連續(xù)的,頁(yè)也是連續(xù)的,每個(gè)頁(yè)的大小一樣,從0開(kāi)始給每個(gè)頁(yè)編號(hào),每個(gè)頁(yè)用struct page表示,存放在一個(gè)大數(shù)組里。因此對(duì)于任何一個(gè)地址,只要除以頁(yè)的大小,就可以得到對(duì)應(yīng)頁(yè)的編號(hào),根據(jù)下標(biāo)就可以找到對(duì)應(yīng)的struct page結(jié)構(gòu),這種模型是最經(jīng)典的平坦內(nèi)存模型:

Linux內(nèi)存管理

  所有的CPU總是通過(guò)總線去訪問(wèn)內(nèi)存,這是最經(jīng)典的內(nèi)存使用方法,它可以使用平坦內(nèi)存模型來(lái)管理內(nèi)存:

1

  在這種模式下,所有的CPU都在總線的一側(cè),所有的內(nèi)存組成一大塊內(nèi)存在總線的另外一側(cè),CPU訪問(wèn)內(nèi)存都需要通過(guò)總線訪問(wèn),而且距離都是一樣的,這種模式稱為SMP(Symmetric multiprocessing),即為對(duì)稱多處理器。這種模式有一個(gè)顯著的缺點(diǎn),就是每個(gè)CPU訪問(wèn)內(nèi)存都需要通過(guò)總線,那么總線就會(huì)成為瓶頸:

2

  為了提高性能,有了一種更加高級(jí)的模式,NUMA(Non-uniform memory access),非一致內(nèi)存訪問(wèn)。這種模式下,內(nèi)存不是組成連續(xù)的一大塊,而是每個(gè)CPU都有自己的一塊內(nèi)存,CPU訪問(wèn)內(nèi)存不需要經(jīng)過(guò)總線,所以速度上會(huì)更快,每個(gè)CPU和內(nèi)存組成一個(gè)NUMA節(jié)點(diǎn)。但是在本地內(nèi)存不足的情況下,每個(gè)CPU會(huì)去其他NUMA節(jié)點(diǎn)申請(qǐng)內(nèi)存,此時(shí)內(nèi)存的訪問(wèn)時(shí)間就比較長(zhǎng)

  這樣內(nèi)存被分為多個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)都分成一個(gè)一個(gè)的頁(yè)。由于頁(yè)是全局唯一定位的,所以每個(gè)頁(yè)都需要有一個(gè)全局唯一的頁(yè)號(hào)。但是由于物理內(nèi)存不再是連續(xù)的,所以頁(yè)號(hào)也不是連續(xù)的,于是內(nèi)存模型就變成了非連續(xù)內(nèi)存模型,管理起來(lái)就會(huì)比較復(fù)雜。

  二、節(jié)點(diǎn):

  下面解析當(dāng)前主流場(chǎng)景,NUMA方式。

  為了表示一個(gè)NUMA節(jié)點(diǎn),內(nèi)核定義了struct pglist_struct這樣一個(gè)結(jié)構(gòu)體,如下:

3

  每個(gè)節(jié)點(diǎn)都有自己的ID:node_id

  node_mem_map是這個(gè)節(jié)點(diǎn)struct page數(shù)組,用于描述這個(gè)節(jié)點(diǎn)所有的頁(yè)

  node_start_pfn是這個(gè)節(jié)點(diǎn)的起始頁(yè)號(hào)

  node_spanned_pages是整個(gè)物理內(nèi)存包含的頁(yè)數(shù)目(包括空洞)

  node_present_pages是真正可用的物理頁(yè)數(shù)目

  例如:64M物理內(nèi)存隔著4M的空洞,然后再是另外的64M,換算成頁(yè)數(shù)目,分別是16K、1K、16K。那么node_spanned_pages就是33K,node_spanned_pages就是32K

  每個(gè)節(jié)點(diǎn)被分為一個(gè)一個(gè)的區(qū)域zone,存放在node_zones數(shù)組中,數(shù)組的大小為MAX_NR_ZONES,定義如下:

4

  這里說(shuō)明以下,這些分區(qū)都是對(duì)物理內(nèi)存的說(shuō)明:

  ZONE_DMA:用作DMA的物理內(nèi)存

  ZONE_DMA32:對(duì)于64位CPU,還有這個(gè)DMA區(qū)域

  ZONE_NORMAL:就是直接映射區(qū)

  ZONE_MOVABLE:可移動(dòng)區(qū)域,通過(guò)將物理內(nèi)存劃分為可移動(dòng)分配區(qū)域和不可移動(dòng)分配區(qū)域來(lái)避免內(nèi)存碎片

  __MAX_NR_ZONES:內(nèi)存區(qū)域的數(shù)量

  內(nèi)核中有一個(gè)數(shù)組用來(lái)存放節(jié)點(diǎn):

5

  三、區(qū)域:

  到這里,將內(nèi)存分為節(jié)點(diǎn),將節(jié)點(diǎn)分為區(qū)域,下面來(lái)看一看區(qū)域的定義

  區(qū)域是zone結(jié)構(gòu)體表示:

6

  zone_start_pfn:表示這個(gè)屬于這個(gè)zone的第一個(gè)頁(yè)

  spanned_pages:注釋里有spanned_pages = zone_end_pfn - zone_start_pfn,表示spanned_pages就是結(jié)束頁(yè)面減去起始頁(yè)面的頁(yè)面數(shù),不管中間是否存在空洞

  present_pages:注釋里有spanned_pages - absent_pages(pages in holes),表示減去空洞后的頁(yè)面數(shù)

  managed_pages:注釋中有managed_pages = present_pages - reserved_pages,表示這個(gè)zone中被伙伴系統(tǒng)管理的所有的page數(shù)目

  per_cpu_pageset:用于區(qū)分冷熱頁(yè)。什么是冷熱頁(yè)?指的是一個(gè)頁(yè)是否被加載進(jìn)CPU的高速緩存中。

  四、頁(yè):

  在了解區(qū)域后,再來(lái)看組成物理內(nèi)存最基本的單位頁(yè),頁(yè)的數(shù)組結(jié)構(gòu)使用struct page表示。這個(gè)結(jié)構(gòu)體定義非常的復(fù)雜,因?yàn)橹С侄喾N使用模式,所以定義了許多union:

7

  第一模式:

  要用就使用一整頁(yè)。這一整頁(yè)的內(nèi)存要么直接跟虛擬地址建立映射關(guān)系,這中稱為匿名頁(yè)(Anonymous Page)。或者關(guān)聯(lián)一個(gè)文件,然后再跟虛擬地址建立映射

  如果某一頁(yè)使用此模式,那么union就使用以下的結(jié)構(gòu):

  struct address_space *mapping 就是用于內(nèi)存映射,如果是匿名頁(yè),最低位為1;如果是映射文件,最低位為0

  pgoff_t index 是映射區(qū)的偏移量

  atomic_t _mapcount 每個(gè)進(jìn)程都有自己的頁(yè)表,這個(gè)變量是指有多少個(gè)頁(yè)表映射到這個(gè)物理頁(yè)

  struct list_head lru 表示這一頁(yè)應(yīng)該在鏈表上,如果這一頁(yè)被換出,那么就應(yīng)該在換出頁(yè)的鏈表中

  compound相關(guān)的變量用于復(fù)合頁(yè),就是將物理上連續(xù)的兩個(gè)或者多個(gè)看成一個(gè)獨(dú)立的大頁(yè)

  第二種模式:

  僅需要分配一小塊內(nèi)存,并不需要一整頁(yè)。為了滿足這種需求,Linux系統(tǒng)采用了一種被稱為slab allocator的技術(shù),用于分配slab中的一小塊內(nèi)存。它的基本工作原理是申請(qǐng)一整塊頁(yè),然后劃分成許多小塊的存儲(chǔ)池,用復(fù)雜的隊(duì)列來(lái)維護(hù)這些小塊的狀態(tài)(被分配了 / 被放回池子了 / 應(yīng)該被回收)

  slab對(duì)于隊(duì)列的維護(hù)過(guò)于復(fù)雜,后來(lái)出現(xiàn)了一種不使用隊(duì)列的分配器slub allocator,它保留的slab的用戶接口,可以把它看作是slab的另一種實(shí)現(xiàn)

  還有一種小塊內(nèi)存的分配器slob

  如果某一頁(yè)被切分為一小塊一小塊,那么union中就會(huì)使用以下結(jié)構(gòu):

  s_mem 是已經(jīng)分配了正在使用的slab的第一個(gè)對(duì)象

  freelist 是池子的空閑對(duì)象

  rcu_head 是需要釋放的列表

  五、頁(yè)的分配:

  前面講了物理內(nèi)存的組織,從NUMA節(jié)點(diǎn)到區(qū)域到頁(yè)再到小塊。接下倆看物理內(nèi)存的分配

  對(duì)于要分配比較大的內(nèi)存,例如分配頁(yè)級(jí)別的,可以使用伙伴系統(tǒng)(Buddy System)

  Linux內(nèi)存管理的頁(yè)大小為4K。把所有空閑的頁(yè)分組為11個(gè)頁(yè)塊鏈表,每個(gè)鏈表管理相應(yīng)大小的頁(yè)塊,有1、2、4、8、16、32、64、128、256、512、1024個(gè)連續(xù)頁(yè)的頁(yè)塊。最大可以申請(qǐng)1024個(gè)連續(xù)的頁(yè),對(duì)應(yīng)4M大小的連續(xù)內(nèi)存。每個(gè)頁(yè)塊第一頁(yè)的起始地址是該頁(yè)塊大小的整數(shù)倍:

8

  在 struct zone 里面有以下的定義:

  struct free_area free_area[MAX_ORDER];

  MAX_ORDER表示2的指數(shù):

  #define MAX_ORDER 11

  當(dāng)申請(qǐng)的頁(yè)塊大小介于free_area中兩個(gè)頁(yè)塊大小之間時(shí),會(huì)選取更大的一個(gè)頁(yè)塊大小,或者如果對(duì)應(yīng)的大小沒(méi)有空閑的頁(yè)塊,那么也會(huì)分配一個(gè)更大的頁(yè)塊。在得到一個(gè)更大的頁(yè)塊后,會(huì)將其進(jìn)行拆分,然后將空閑的頁(yè)塊繼續(xù)插入到對(duì)應(yīng)頁(yè)塊大小的鏈表中

  例如申請(qǐng)一個(gè)128個(gè)頁(yè)的頁(yè)塊,如果沒(méi)有,那么就找256,然后一直如此,直到能夠找到。如果找到的是256個(gè)頁(yè)的頁(yè)塊。那么就會(huì)將其拆分為128和128個(gè)頁(yè)大小的頁(yè)塊,然后將一個(gè)空閑的頁(yè)塊添加到128對(duì)應(yīng)的頁(yè)塊鏈表中

  對(duì)于這些內(nèi)容,可以在 alloc_pages 函數(shù)中找到定義:

9

  order:表示分配2的指數(shù)個(gè)頁(yè)的頁(yè)塊

  gfp:分配標(biāo)志,表示要分配那么區(qū)域的物理頁(yè)

  GFP_USER 表示分配一個(gè)頁(yè)映射到用戶虛擬地址空間,并且希望直接被內(nèi)核或者硬件訪問(wèn),主要用于一個(gè)用戶進(jìn)程希望通過(guò)內(nèi)存映射的方式,訪問(wèn)硬件緩存(如顯卡緩存)

  GFP_KERNEL 用于內(nèi)核中分配頁(yè),主要分配 ZONE_NORMAL 區(qū)域的內(nèi)存

  GFP_HIGHMEM 用于分配高端區(qū)域的物理內(nèi)存

  接下來(lái)調(diào)用 get_page_from_freelist,這是伙伴系統(tǒng)的核心。它會(huì)先循環(huán)查找對(duì)應(yīng)節(jié)點(diǎn)的zone,如果找不到,那么就看備用節(jié)點(diǎn)的zone:

10

  每一個(gè)zone,都有伙伴系統(tǒng)維護(hù)的各種大小的隊(duì)列

  rmqueue 就是找到合適大小的隊(duì)列,然后將頁(yè)塊取下來(lái)

  最終會(huì)調(diào)用到 __rmqueue_smallest:

11

  從指定的區(qū)域中,按照當(dāng)前指定的指數(shù)開(kāi)始查找,如果找不到,那么就到更大的指數(shù)查找。除了將頁(yè)塊從鏈表取下,還要將多余的頁(yè)面插入到合適的鏈表中,expand 就是完成這個(gè)工作:

12

  六、總結(jié):

  如果有多個(gè)CPU,就會(huì)有多個(gè)NUMA節(jié)點(diǎn)。每個(gè)節(jié)點(diǎn)使用 struct pglist_data 表示,存放在一個(gè)數(shù)組中

  每個(gè)節(jié)點(diǎn)分為多個(gè)區(qū)域,每個(gè)區(qū)域使用 struct zone 表示,也存放在一個(gè)數(shù)組中

  每個(gè)區(qū)域分為多個(gè)頁(yè),空閑頁(yè)存放在 struct free_area 中,使用伙伴系統(tǒng)進(jìn)行管理和分配

  每一頁(yè)都是使用 struct page 表示:

13

tags:
聲明:本站稿件版權(quán)均屬千鋒教育所有,未經(jīng)許可不得擅自轉(zhuǎn)載。
10年以上業(yè)內(nèi)強(qiáng)師集結(jié),手把手帶你蛻變精英
請(qǐng)您保持通訊暢通,專屬學(xué)習(xí)老師24小時(shí)內(nèi)將與您1V1溝通
免費(fèi)領(lǐng)取
今日已有369人領(lǐng)取成功
劉同學(xué) 138****2860 剛剛成功領(lǐng)取
王同學(xué) 131****2015 剛剛成功領(lǐng)取
張同學(xué) 133****4652 剛剛成功領(lǐng)取
李同學(xué) 135****8607 剛剛成功領(lǐng)取
楊同學(xué) 132****5667 剛剛成功領(lǐng)取
岳同學(xué) 134****6652 剛剛成功領(lǐng)取
梁同學(xué) 157****2950 剛剛成功領(lǐng)取
劉同學(xué) 189****1015 剛剛成功領(lǐng)取
張同學(xué) 155****4678 剛剛成功領(lǐng)取
鄒同學(xué) 139****2907 剛剛成功領(lǐng)取
董同學(xué) 138****2867 剛剛成功領(lǐng)取
周同學(xué) 136****3602 剛剛成功領(lǐng)取
相關(guān)推薦HOT
為什么SpringBoot的 jar 可以直接運(yùn)行?

一、JAR文件的結(jié)構(gòu)與執(zhí)行方式Spring Boot的JAR包是Java Archive的縮寫,它是一種壓縮文件格式,可以將Java項(xiàng)目的類文件、資源文件以及依賴庫(kù)等...詳情>>

2023-10-14 23:01:49
站群服務(wù)器是什么?

站群服務(wù)器的含義與用途站群服務(wù)器主要用于支持站群,即由一組相互鏈接的網(wǎng)站組成的群體。這些網(wǎng)站通常由同一組織或個(gè)人擁有,并且經(jīng)常會(huì)互相鏈...詳情>>

2023-10-14 22:46:12
自編碼器是什么?

一、自編碼器原理自編碼器的設(shè)計(jì)靈感源于神經(jīng)科學(xué)中關(guān)于感知系統(tǒng)的認(rèn)知原理,它的核心思想是將輸入數(shù)據(jù)經(jīng)過(guò)編碼過(guò)程,形成一個(gè)隱藏層的特征表示...詳情>>

2023-10-14 22:41:10
什么是云網(wǎng)融合?

一、云網(wǎng)融合的定義云網(wǎng)融合是指將云計(jì)算與網(wǎng)絡(luò)技術(shù)相結(jié)合,實(shí)現(xiàn)資源的共享、業(yè)務(wù)的協(xié)同,將網(wǎng)絡(luò)與云端服務(wù)深度融合,提供更靈活、高效、安全的...詳情>>

2023-10-14 22:31:47
什么是setnx、Redlock、Redisson?

一、setnxsetnx是Redis中的一個(gè)命令,用于將鍵值對(duì)(key-value)設(shè)置到Redis數(shù)據(jù)庫(kù)中。其中,setnx表示”Set if Not Exists”,即當(dāng)...詳情>>

2023-10-14 22:22:53