Linux kernel之二內(nèi)存管理之進(jìn)程虛擬地址空間

1.背景

虛擬內(nèi)存的一大優(yōu)勢就是每個進(jìn)程有自己的虛擬地址空間君躺,OS 負(fù)責(zé)將其虛擬地址空間映射到物理內(nèi)存中驰吓。
內(nèi)核處理用戶部分的地址空間的方式姿鸿,與內(nèi)核部分不同:

  • 內(nèi)核部分內(nèi)存的分配是立刻滿足的,并對全局可見:
    1)__get_free_pages()或alloc_pages() 從page frame 分配器獲取page frame;
    2)kmem_cache_alloc() 或kmalloc() 使用專用或通用的slab 分配器分配objects砰粹;
    3)vmalloc() 獲取非連續(xù)的內(nèi)存。
    如此簡單的分配方式的兩個原因是:
    1)內(nèi)核是整個OS中優(yōu)先級最高的部分造挽;
    2)內(nèi)核可靠安全碱璃,所有內(nèi)核函數(shù)都是無error的,不需要加入保護(hù)以防止錯誤
  • 用戶進(jìn)程情況刽宪,則不同
    1)進(jìn)程內(nèi)存申請的請求厘贼,通常內(nèi)核會推遲分配內(nèi)存給用戶進(jìn)程;
    i. 每個進(jìn)程通常實際使用的地址空間圣拄,就只有整個虛擬地址空間的其中的幾個區(qū)域嘴秸;并且每個區(qū)域相隔比較遠(yuǎn)。 內(nèi)核需要高效管理這些分散的區(qū)域庇谆。
    ii. 進(jìn)程可執(zhí)行文件加載時岳掐,進(jìn)程不可能在不遠(yuǎn)的將來會訪問所有的code page;
    iii. 進(jìn)程通過malloc()分配內(nèi)存時,并不意味著進(jìn)程會很快訪問所有分配的內(nèi)存
    2)用戶進(jìn)程并不可靠饭耳,內(nèi)核必須捕捉所有用戶態(tài)的錯誤以確保用戶進(jìn)程會破壞系統(tǒng)穩(wěn)定性和安全性串述。

2. 進(jìn)程虛擬地址空間

2.1 進(jìn)程虛擬地址空間布局

(1)進(jìn)程虛擬地址空間由很多虛擬內(nèi)存區(qū)域(VMA)構(gòu)成:

  • stack
    用于存放局部變量,函數(shù)參數(shù)和函數(shù)調(diào)用
  • mmap
    主要用于映射文件內(nèi)容到虛擬地址空間的內(nèi)存映射,也用于映射共享object 和動態(tài)庫
  • heap
    動態(tài)分配的內(nèi)存存放的地方寞肖,允許進(jìn)程存放運(yùn)行時的數(shù)據(jù)纲酗。malloc()分配的內(nèi)存來自此區(qū)域
  • BSS
    存放未初始化的靜態(tài)變量
  • data
    存放全局變量衰腌,靜態(tài)初始化的變量
  • text
    映射程序二進(jìn)制文件到內(nèi)存的區(qū)域
    image.png

(2)每個VMA, 物理上映射到一到多個內(nèi)存塊觅赊,進(jìn)程的page table 做相應(yīng)的地址映射右蕊。

2.2 進(jìn)程地址空間描述符

  • 進(jìn)程可用的地址空間通過進(jìn)程task_struct 中的struct mm_struct 結(jié)構(gòu)管理
  • 每個進(jìn)程有一個mm_struct ,用戶線程共享同一個地址空間;
  • 通過尋找所有task_structs 中指向相同的mm_struct 可以識別出task list 中的線程吮螺;
  • 內(nèi)核線程不需要mm_struct饶囚,通常內(nèi)核線程的task_struct->mm為NULL;
image.png
  • mmap
    是進(jìn)程地址空間中所有VMA 區(qū)域的鏈表頭
  • mmap_cache
    緩存上次訪問的VMA鸠补;
  • mm_rb
    所有的VMA 排放在鏈表mm_struct->mmap中萝风,并為了快速查詢,也放在紅黑樹中紫岩,這個是樹的root
image.png
  • start_code, end_code
    對應(yīng)程序二進(jìn)制文件映射的code VMA 區(qū)域的起始和結(jié)束虛擬地址
  • start_data, end_data
    對應(yīng)data VMA 區(qū)域的起始和結(jié)束虛擬地址
  • start_brk, brk
    對應(yīng)heap VMA 區(qū)域的起始和當(dāng)前結(jié)束的虛擬地址
  • start_stack
    對應(yīng)stack VMA 區(qū)域的起始和當(dāng)前結(jié)束的虛擬地址
  • arg_start, arg_end
    對應(yīng)命令行參數(shù)列表的 VMA 區(qū)域的起始和當(dāng)前結(jié)束的虛擬地址
  • env_start, env_end
    對應(yīng)環(huán)境參數(shù)的 VMA 區(qū)域的起始和當(dāng)前結(jié)束的虛擬地址


    image.png

2.3 虛擬內(nèi)存區(qū)域VMA

  • 每個虛擬內(nèi)存區(qū)域由vm_area_struct 管理


    image.png
  • VMA 區(qū)域之間不會重疊规惰,每個VMA區(qū)域代表著相同保護(hù)訪問方式和目的的的區(qū)域
  • 進(jìn)程的完整的VMA區(qū)域可通過/proc/PID/maps 查看
  • vm_start, vm_end
    對應(yīng)這個該vma 區(qū)域的起始虛擬地址和結(jié)束地址
  • vm_next
    VMA直接通過vm_next 鏈接到一起,通過地址排序
  • vm_rb
    VMA 通過vm_rb 鏈接到紅黑樹中
  • vm_mm
    指向所屬的進(jìn)程的mm_struct 結(jié)構(gòu)
  • vm_file
    對于基于文件的VMA 區(qū)域(code 區(qū)被因,共享庫卿拴,共享內(nèi)存映射區(qū)等等)衫仑,vm_file 指向?qū)?yīng)文件的struct file 指針梨与,該文件struct file ->f_dentry->d_inode->i_mapping 的struct address_space 擁有所有關(guān)于文件的信息,包含指向文件系統(tǒng)操作的文件系統(tǒng)函數(shù)
  • anon_vma_node
    heap文狱,stack 和mmap 的虛擬地址空間的分配都通過匿名內(nèi)存映射分配的, 內(nèi)核通過struct anon_vma 將代表匿名內(nèi)存的VMA區(qū)域鏈接到一起粥鞋,便于快速訪問所有的映射匿名頁的進(jìn)程VMA
  • vm_ops
    VMA 操作指針,open 和close 通常為NULL瞄崇,nopage 用于page fault


    image.png
  • vm_operations_struct


    image.png

2.4 基于文件的VMA區(qū)域

  • 基于文件的VMA 區(qū)域 通過struct address_space 描述


    image.png
  • 每個address_space結(jié)構(gòu)作為一個文件inode 對應(yīng)的pages 的抽象
    i. 文件打開的時候呻粹,kernel 設(shè)置file->f_mapping為inode->i_mapping
    ii. inode 是per-file 數(shù)據(jù)結(jié)構(gòu),而file 是per-process 數(shù)據(jù)結(jié)構(gòu)苏研;這樣讓多個進(jìn)程能直接訪問同樣的文件等浊,而不需要與其他進(jìn)程交互


    image.png
image.png
  • host
    指向擁有對于pages的owner inode;

  • i_mmap
    為了高效管理cache 中的文件pages, 需要跟蹤所有映射到同一個address_space的VMA摹蘑。 i_mmap 是所有包含當(dāng)前映射到該address_space的VMA的紅黑樹筹燕。

  • page_tree
    i. 處于address_space對象的所有包含文件數(shù)據(jù)的物理page 都通過radix tree 數(shù)據(jù)結(jié)構(gòu)組織管理起來以高效訪問,page_tree 是radix tree 的root衅鹿,是struct radix_tree_root 類型的實例撒踪;
    ii. 一方面一個進(jìn)程的所有VMA 被同時組織管理在一個鏈表和紅黑樹數(shù)據(jù)結(jié)構(gòu)中
    iii. 另一方面radix 樹數(shù)據(jù)結(jié)構(gòu)用于反向查找一個給定文件的所有VMA;


    image.png

    image.png

    image.png
  • struct radix_tree_root
    radix tree 的每個node 是struct radix_tree_node 類型的,struct radix_tree_root 中的*rnode 作為radix tree的 第一個node;


    image.png

    image.png

2.6 文件的虛擬地址空間與文件系統(tǒng)之間的聯(lián)系

  • 文件的內(nèi)存映射是兩個不同地址空間的映射
    i. 一個地址空間是用戶進(jìn)程的虛擬內(nèi)存地址空間大渤;
    ii. 另一個是文件系統(tǒng)覆蓋的地址空間制妄;

  • 內(nèi)核以read, write 請求的方式建立兩個地址空間的聯(lián)系

  • vm_operations_struct 結(jié)構(gòu)體用于建立聯(lián)系,提供方法讀內(nèi)容到物理內(nèi)容


    image.png
  • 而具體的文件系統(tǒng)的操作是通過address_space 結(jié)構(gòu)的address_space_operation
    i. readpage,readpages 讀塊設(shè)備的單個和多個頁內(nèi)容到內(nèi)存中泵三;
    ii.writepage耕捞,writepages 寫內(nèi)存中的單個頁和多個頁到塊設(shè)備中對應(yīng)的位置
    iii. set_page_dirty 標(biāo)記頁內(nèi)容改變衔掸,不在與塊設(shè)備中的內(nèi)容一致


    image.png
  • vm_operation_struct 與 address_space 之間的聯(lián)系
    i. 通過kernel 的標(biāo)準(zhǔn)實現(xiàn)vm_operations_struct 實例,幾乎所有文件系統(tǒng)在使用 generic_file_vm_ops.

  • filemap_faul的實現(xiàn)使用底層文件系統(tǒng)對應(yīng)的address_space提供的readpage 操作


    image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末俺抽,一起剝皮案震驚了整個濱河市具篇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凌埂,老刑警劉巖驱显,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瞳抓,居然都是意外死亡埃疫,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門孩哑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栓霜,“玉大人,你說我怎么就攤上這事横蜒「炻” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵丛晌,是天一觀的道長仅炊。 經(jīng)常有香客問我,道長澎蛛,這世上最難降的妖魔是什么抚垄? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮谋逻,結(jié)果婚禮上呆馁,老公的妹妹穿的比我還像新娘。我一直安慰自己毁兆,他們只是感情好浙滤,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著气堕,像睡著了一般纺腊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上送巡,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天摹菠,我揣著相機(jī)與錄音,去河邊找鬼骗爆。 笑死次氨,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的摘投。 我是一名探鬼主播煮寡,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼虹蓄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了幸撕?” 一聲冷哼從身側(cè)響起薇组,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎坐儿,沒想到半個月后律胀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡貌矿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年炭菌,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逛漫。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡黑低,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出酌毡,到底是詐尸還是另有隱情克握,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布枷踏,位于F島的核電站菩暗,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏呕寝。R本人自食惡果不足惜勋眯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一婴梧、第九天 我趴在偏房一處隱蔽的房頂上張望下梢。 院中可真熱鬧,春花似錦塞蹭、人聲如沸孽江。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岗屏。三九已至,卻和暖如春漱办,著一層夾襖步出監(jiān)牢的瞬間这刷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工娩井, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留暇屋,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓洞辣,卻偏偏與公主長得像咐刨,于是被迫代替她去往敵國和親昙衅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容