日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

《深入理解Linux内核》笔记5:内存管理

發布時間:2023/11/29 linux 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《深入理解Linux内核》笔记5:内存管理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文介紹內核如何給自己分配物理內存并管理。對應《深入》第8章。

在《深入》第2章“內存尋址”(或者是我博客中的這篇文章,點這里)中,已經介紹了內核如何給自己分配1G的線性地址的。但是物理內存的分配及管理恐怕更復雜而且更有必要:內存分配和釋放的速度(由內存管理的算法決定)影響內核的工作效率。

首先介紹概念:

頁框:通俗的說就是物理內存上的單元。請注意與“頁”的區別。頁有兩重意思,不過最多的用法是指線性地址的單元。所以一個是實際物理內存的單元,一個是線性地址/虛擬內存的單元。在大多數情況下,頁框大小等于頁的大小,為4KB,使得一個頁框恰好可以容納一個頁的數據。

(1)為什么要進行內存管理?

內存管理的目的總體上說無非是兩點:提高時間效率和提高空間效率。時間效率也就是盡量使尋找到空閑內存、分配和釋放這塊內存的時間更短。空間效率就是指盡量能找到合適大小的空間,并減少內存空間浪費。

關于空間效率,舉個簡單的例子:切蛋糕。當我們拿到一塊完整的蛋糕的話,如果想每個人都吃到完整的一塊,那么我們當然不能沒有計劃的切塊。雖然總量是不變的,但是如果隨便亂切,橫七豎八,勢必導致最后剩下的蛋糕都是碎塊,那么后面吃蛋糕的同學必然只能把小塊小塊的蛋糕湊成一大塊來吃。勢必很不爽啊。。。

(2)關鍵數據結構:頁描述符

如果需要對一個東西進行管理,那么必須要有負責管理的數據結構,這個數據結構中有各個字段,用來提供不同的管理功能。舉例子:比如為了保護內核的內存不被用戶進程使用,就必須使用一個標志位;用戶進程在讀寫內存時,首先就要檢查這個標志位,然后才能讀寫。

所以內核使用了“頁描述符”這個數據結構,頁描述符的類型是page,長度為32字節(是字節哦),所有的頁描述符放在一個數組mem_map中。我個人覺得好像應該叫“頁框描述符”比較好。

(3)為什么要使用內存管理區?

內存本來在物理上是一個實體,并不分區的。有人會問:這樣的一個整體進行處理不是很簡潔么?為什么要分區呢?

但是由于以下的兩種約束,我們迫不得已給自己增加了負擔,將內存分區來管理。

約束一:DMA。這個名詞不再解釋,請自行google。在進行DMA數據傳輸時,DMA控制器只能對16M的內存進行尋址,所以被迫無奈,只好將這16M的物理內存固定劃分給DMA了。

約束二:線性地址有限,無法直接大的物理內存。所以,超出896M的物理內存必須被區別對待。

所以,最終,物理內存被分配成3個管理區:ZONE_DMA,ZONE_NORMAL,ZONE_HIGHMEM。

(4)為什么要使用伙伴系統(Buddy system)算法?

使用伙伴系統的直接目的就是為了防止物理內存“外碎片”的產生。關于外碎片,簡而言之就是雖然我們一直分配或者釋放連續的內存,但是結果就是我們的內存變得很不連續,充滿了大大小小的碎片或者是洞,以至于我們無法再分配足夠大的一塊連續的內存。(回憶下我們剛才說過的蛋糕的例子)

下面舉例說明。假設我們要分配一塊256個連續頁框的內存。

首先考慮一種不好的分配算法作為對比,例如:將所有的空閑連續頁框鏈在一個鏈表中,我們在分配空間時選取遇到的第一個大于256個連續頁框(這個可能很隨機,可能是1024個頁框,也可能是512個,也可能恰好是256個;而且我們不能奢望在鏈表的開頭遇到大于256個的連續頁框,如果鏈表很長。。。Orz)。假設我們遇到了空閑的1024個頁框。這時候我們面臨兩個選擇:

??? (a)把這1024個頁框都分配出去。這顯然是一種巨大的浪費。

??? (b)把這1024個頁框切開,將256個連續頁框脫離鏈表,然后鏈表上剩下了768個連續頁框的塊。這其實和外碎片沒有什么區別(因為鏈表后面很可能有更適合256的連續頁框,比如257個或者258個連續頁框),最終會導致這個鏈表被分割的亂七八糟,以至于再也找不到一塊合適的連續空間。

(5)伙伴系統

所以,Linux使用了著名的伙伴系統來處理這個問題。那么下面用實例說明伙伴系統是如何改進的。最后我們再總結一下伙伴系統的思想。

伙伴系統的基礎是11個連續頁框鏈表,第一個鏈表上只存儲所有空閑的1個頁框,第二個鏈表上只儲存所有空閑的2個連續頁框,以此類推。這11個鏈表將不同大小的連續內存塊鏈在不同的鏈表上,這首先節省了遍歷一個很長的鏈表的時間,可是使我們直奔最符合需求的連續內存。如果是需要256個連續頁框,我們可以直接找到第9個鏈表,取出一個即可。但又出現了幾個問題:(q1)如果我們需要254個連續頁框呢?(q2)如果我們已經沒有了256個的連續頁框,即256個連續頁框的鏈表已經空了呢?

下面介紹如何妥善處理剩余部分,也就是解決問題q1。我們只需要254個連續頁框時,我們把這個256個連續頁框從鏈表上切除,但是只分配出去254個頁框,剩余的兩個連續頁框鏈入屬于它的鏈表,也就是存儲所有兩個連續頁框的鏈表。這樣我們看到,我們一個頁框都沒有浪費。

有人可能會問,如果需要258個連續頁框怎么辦(258>256)?這個問題其實與q1等價,但是此時最符合需求的是512個連續頁框,但是剩下的部分只是要切割多次。但我們無需證明最后一個頁框都不會浪費(因為至少最后都會鏈到1個頁框的鏈表里)。q2其實與這種情況很類似,仍然要去更大的一級鏈表中尋找。

那么伙伴系統與開始介紹的那種不好的算法到底有什么本質區別呢?

簡而言之,伙伴系統直奔最符合需求的連續內存,然后它妥善的處理了剩余部分。首先我們使用了空間換時間的算法:維護這11個塊鏈表的開銷,相對于一個好的內存分配算法根本算不上什么。其次,伙伴系統是類似“貪心”的。它尋找當前認為最好的。最后,它把分配后剩余的部分妥善的移動到它們最應該去的地方。

(6)使用的函數

分配:alloc_pages()/alloc_page()/__alloc_pages()

釋放:__free_pages()/free_pages()/free_page()

==============================

下面插入兩個概念,內存區(memory area)與內碎片。內存區這個詞很容易讓人產生誤會,它不是指整個內存,而是指連續的任意長度的物理內存區。而內碎片是相對于外碎片講的,外碎片是以頁框為單位的,在頁框之外;而內碎片就是在頁框內部的碎片。產生內碎片的原因其實與外碎片一致:雖然我們所有的分配和釋放都是連續的,但最后結果卻是不連續的物理內存。

===============================

(7)為什么要使用slab分配器?

我們先不管slab是什么,先考慮為什么要使用它:它的出現就是為了解決內碎片的問題。

當然,有人肯定會想,使用伙伴系統解決內碎片不是一樣么?只不過把單位從頁框改為字節。

早期Linux確實是這么做的。但是遇到了一些問題(詳見《深入》p.324),以我的理解就是:當分配和釋放的粒度變細時,被迫需要考慮更多的因素,比如說需要考慮到數據類型。所以伙伴系統在處理內碎片時效率并不是最好的。

于是采用了具有面向對象思想(考慮到數據類型,就已經是一種面向對象的思想了)的slab系統。

(8)slab系統的思想的。。。呃 猜測

這里,限于篇幅和個人能力有限,就不詳細介紹slab系統了。我的理解是:slab系統提供了一種快速查找并分配特定類型的數據(面向對象)的細粒度連續內存空間的方法。因為它使用了下圖所示的這種層級結構,讓我不由得聯想到了數據結構中的B樹(B樹也是用來快速查找,減少樹的層數的,當然也付出了一定的空間復雜度;當然我還不知道我這種聯想合理不合理)。

(9)slab所使用的函數

分配和釋放slab:kmem_cache_alloc()/kmem_cache_free()

分配和釋放對象:kmalloc()/kfree()。

======================================

參考資料:

這里有一篇IBM關于slab的技術文章:Linux slab 分配器剖析。


轉載于:https://www.cnblogs.com/microgrape/archive/2011/05/12/2043909.html

總結

以上是生活随笔為你收集整理的《深入理解Linux内核》笔记5:内存管理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。