乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      簡(jiǎn)述Linux虛擬內(nèi)存管理

       lifei_szdz 2019-04-17

      原文地址:https://cloud.tencent.com/ developer/article/1157420

      虛擬存儲(chǔ)

      虛擬存儲(chǔ)(virtual memory, VM)的基本思想是: 維護(hù)一個(gè)虛擬的邏輯內(nèi)存機(jī)制(通常比物理內(nèi)存大得多), 進(jìn)程都基于這個(gè)虛擬內(nèi)存, 在進(jìn)程運(yùn)行時(shí)動(dòng)態(tài)的將虛擬內(nèi)存地址映射到實(shí)際的物理內(nèi)存.

      VM的設(shè)計(jì)體現(xiàn)了軟件工程思想: 封裝, 抽象, 依賴倒置, 非常棒. 每個(gè)運(yùn)行中的進(jìn)程無(wú)需再去關(guān)心實(shí)際物理內(nèi)存是多大, 分配內(nèi)存會(huì)不會(huì)超出限制, 哪些內(nèi)存已經(jīng)被其他進(jìn)程占用等等, 這些都交由kernel的內(nèi)存管理單元來(lái)解決, 暴露給進(jìn)程的"接口"只有每個(gè)進(jìn)程獨(dú)有的虛擬地址空間.

      如上圖所示: 程序中產(chǎn)生的內(nèi)存地址成為虛擬地址(virtual address), 又稱為邏輯地址(logic address), 邏輯地址被送到內(nèi)存管理單元(memory manager unit, MMU), 映射成物理內(nèi)存地址之后, 再送到內(nèi)存總線上.

      分頁(yè)

      MMU的主要職責(zé)就是將邏輯地址, 轉(zhuǎn)成物理地址. 以32位Linux為例, MMU可以當(dāng)成一個(gè)數(shù)學(xué)函數(shù): f(x) = y, 輸入x是一個(gè)0-4G范圍內(nèi)的邏輯地址, 輸出y是實(shí)際的物理地址.

      最簡(jiǎn)單暴力的方法, 莫過(guò)于直接建一層映射關(guān)系, 不過(guò)這樣映射表就得4G大小了……

      因?yàn)閷?shí)際上我們并不需要把所有的映射關(guān)系都建立起來(lái), 而只需要為用到的內(nèi)存做映射, 所以, 前輩們用了分頁(yè)的方法來(lái)解決這個(gè)問題(實(shí)際是一個(gè)多階哈希).

      一個(gè)典型的二級(jí)頁(yè)表來(lái)處理分頁(yè): 32位的邏輯地址被分成了3段, 10位的一級(jí)頁(yè)表索引(page table 1 index), 10位的二級(jí)頁(yè)表索引(page table 2 index)和剩下的12位頁(yè)面偏移量(page offset). 所謂頁(yè)面(page), 是現(xiàn)在大部分MMU中用來(lái)管理內(nèi)存的單位, Linux下常見的page大小是4k(12位的偏移量剛好是一個(gè)page, 即4k).

      對(duì)于一個(gè)進(jìn)程而言, 它需要用到的頁(yè)表: 一級(jí)頁(yè)表,以及部分用到的二級(jí)頁(yè)表(不需要全部的). 以一個(gè)占用16M內(nèi)存地址空間的進(jìn)程為例, 理論上它只需要1個(gè)一級(jí)頁(yè)表, 和4個(gè)二級(jí)頁(yè)表, 頁(yè)表開銷即 5 * 4k = 20k, 能節(jié)省大量的頁(yè)表開銷.

      在多級(jí)頁(yè)表中, 頁(yè)表分級(jí)越多, 越靈活, 但是帶來(lái)的時(shí)間成本也就越高, 復(fù)雜度也越高. 二級(jí), 或者三級(jí)頁(yè)表是一個(gè)比較合理的選擇. 為了兼容不同的CPU, Linux 2.6.11 之后使用了四級(jí)分頁(yè)機(jī)制, 在不同的CPU環(huán)境下可以靈活擴(kuò)展成二級(jí)或者三級(jí).

      邏輯地址映射成物理地址的過(guò)程是通過(guò)MMU硬件來(lái)完成的. 除此之外, 還有一個(gè)TLB的硬件, translation lookaside buffer, 即頁(yè)表緩沖, 它是一塊高速cache, 通過(guò)CR3寄存器來(lái)刷新, 能加速虛擬內(nèi)存尋址的過(guò)程.

      頁(yè)面置換

      進(jìn)程中用到的代碼段, 數(shù)據(jù)段和堆棧的總大小可能超過(guò)可用的物理內(nèi)存總數(shù), VM提供了一種機(jī)制來(lái)解決這個(gè)問題: 把當(dāng)前使用的那一部分放到內(nèi)存中, 其他部分保存在磁盤上, 并在需要時(shí)在磁盤和內(nèi)存中做交換. 這就是頁(yè)面置換.

      當(dāng)一個(gè)邏輯地址, 經(jīng)過(guò)MMU映射后發(fā)現(xiàn), 對(duì)應(yīng)的頁(yè)表項(xiàng)還沒有映射到物理內(nèi)存, 就會(huì)觸發(fā)缺頁(yè)錯(cuò)誤(page fault): CPU 需要陷入 kernel, 找到一個(gè)可用的物理內(nèi)存頁(yè)面, 從頁(yè)表項(xiàng)映射過(guò)去. 如果這個(gè)時(shí)候沒有空閑的物理內(nèi)存頁(yè)面, 就需要做頁(yè)面置換了, 操作系統(tǒng)通過(guò)某些算法, 從物理內(nèi)存中選一個(gè)當(dāng)前在用的頁(yè)面, (是否需要寫到磁盤, 取決于有沒有被修改過(guò)), 重新調(diào)入, 建立頁(yè)表項(xiàng)到之的映射關(guān)系.

      分段

      分段的思想, 說(shuō)穿了就是把內(nèi)存分成若干段, 每個(gè)段是一個(gè)單獨(dú)的地址空間, 有自己的起始的基地址, 根據(jù) 基地址+偏移量 來(lái)做尋址.

      分段的好處是帶來(lái)了比較大的靈活性, 也更安全. 每個(gè)段都構(gòu)成了自己的獨(dú)立地址空間, 增大或者減小而不會(huì)影響其他段. 還可以對(duì)每個(gè)段設(shè)置不同的保護(hù)級(jí)別.

      Linux下采用的是段頁(yè)式內(nèi)存管理, 先分段, 再分頁(yè). 但是因?yàn)長(zhǎng)inux中所有的段基址都設(shè)置成了0, 段偏移量相當(dāng)于就是線性地址, 只用了一個(gè)地址空間, 效果上就是正常的分頁(yè). 這么做的原因是為了兼容各種硬件體系.

      雖然Linux下, "分段"只是一個(gè)擺設(shè), 但是在進(jìn)程的內(nèi)存管理中, 還是應(yīng)用了分段的思想的: 每一個(gè)進(jìn)程在運(yùn)行時(shí), 它的邏輯地址空間都會(huì)被分為代碼段, 數(shù)據(jù)段, 堆, 棧等, 當(dāng)訪問段之外的內(nèi)存地址時(shí), kernel 能監(jiān)測(cè)到并給出段錯(cuò)誤(segment fault).

      VM管理

      Linux kernel 主要提供了兩種內(nèi)存分配算法: buddy 和 slab, 結(jié)合使用。buddy 提供了2的冪大小內(nèi)存塊的分配方法,具有數(shù)組特性,簡(jiǎn)單高效, 但是缺點(diǎn)在于內(nèi)存碎片。slab 提供了小對(duì)象的內(nèi)存分配方法, 實(shí)際上是一個(gè)多級(jí)緩存列表, 最小的分配單位稱為一個(gè)slab(一個(gè)或者多個(gè)連續(xù)頁(yè)), 被分配為多個(gè)對(duì)象來(lái)使用.

      kswapd 是一個(gè) daemon 進(jìn)程, 對(duì)系統(tǒng)內(nèi)存做定時(shí)檢查, 一般是1秒一次. 如果發(fā)現(xiàn)沒有足夠的空閑頁(yè)面, 就做頁(yè)回收(page reclaiming), 將不再使用的頁(yè)面換出. 如果要換出的頁(yè)面臟了, 往往還需要寫回到磁盤或者swap.

      bdflush 也是 daemon 進(jìn)程, 周期性的檢查臟緩沖(磁盤cache), 并寫回磁盤. 不過(guò)在 Linux 2.6 之后, pdflush 取代了 bdflush, 前者的優(yōu)勢(shì)在于: 可以開多個(gè)線程, 而 bdflush 只能是單線程, 這就保證了不會(huì)在回寫繁忙時(shí)阻塞; 另外, bdflush 的操作對(duì)象是緩沖, 而 pdflush 是基于頁(yè)面的, 顯然 pdflush 的效率會(huì)更高.

      觀察內(nèi)存

      "pmap –x pid" 這個(gè)命令, 能將/proc/pid/maps中的數(shù)據(jù), 以更人性化的方式展示出來(lái):

      從上圖可以看到, 每一項(xiàng)內(nèi)容都清晰的標(biāo)出了對(duì)象, 內(nèi)存起始地址(邏輯地址), 占用的內(nèi)存大小, 實(shí)際分配的內(nèi)存(RSS, 也就是常駐內(nèi)存), 以及臟內(nèi)存, 這些單位都是kb, 并給出了最終的統(tǒng)計(jì)結(jié)果. 統(tǒng)計(jì)結(jié)果的前兩項(xiàng)就是 top 中顯示的 VIRT 和 RSS.

      VM tuning

      這里就只關(guān)注 Linux 2.6 之后的情況了(2.4之前諸如 bdflush 就不在討論范圍之內(nèi)). 所有的VM可以調(diào)整的參數(shù)項(xiàng), 都在/proc/sys/vm目錄下:

      可以"sysctl vm.param"觀察參數(shù)的值, "sysctl –w vm.param=value"來(lái)修改參數(shù).具體的每一項(xiàng)參數(shù)的含義可以參考: https://www./doc/Documentation/sysctl/vm.txt.

      1. pdflush調(diào)優(yōu), 其實(shí)這一塊跟磁盤IO關(guān)系比較緊.

      • dirty_writeback_centisecs, 默認(rèn)是500, 單位是毫秒. 意思是每5秒喚醒 pdflush (多個(gè)線程), 將臟頁(yè)面寫回磁盤. 把這個(gè)參數(shù)調(diào)低可以增加 pdflush 被喚醒的頻率, 不過(guò)在內(nèi)核實(shí)現(xiàn)中, pdflush 在需要的時(shí)候會(huì)自動(dòng)被喚醒, 所以這個(gè)參數(shù)的效果不可預(yù)期.

      • dirty_expire_centiseconds, 默認(rèn)是3000, 單位是毫秒, 是指臟頁(yè)面的過(guò)期時(shí)間, 超過(guò)了這個(gè)時(shí)間, 就會(huì)觸發(fā) pdflush 做回寫.

      • dirty_background_ratio, 默認(rèn)是10, 是指總內(nèi)存中臟頁(yè)面的百分比. 低于這個(gè)閾值時(shí), pdflush 才會(huì)停止做回寫, 有的內(nèi)核版本的默認(rèn)值是5.

      • dirty_ratio, 這也是一個(gè)百分比, 默認(rèn)40, 是總內(nèi)存中臟頁(yè)面的百分比. 超過(guò)這個(gè)閾值, 就一定等待 pdflush 向磁盤回寫. 與 dirty_background_ratio 的區(qū)別在與: 如果 cache 的增長(zhǎng)超過(guò)了 pdflush 的回寫速率時(shí), 有可能 pdflush 來(lái)不及回寫, 在超過(guò)40\%這個(gè)閾值時(shí), 進(jìn)程就會(huì)等待, 直到 pdflush 處理到這個(gè)閾值之下. 此時(shí)就是一個(gè)IO瓶頸.

      IO比較重的時(shí)候, 可以考慮的調(diào)優(yōu)手段: 首先嘗試調(diào)低 dirty_background_ratio, 其次是 dirty_background_ratio, 然后是 dirty_expire_centiseconds, dirty_writeback_centisecs 這一項(xiàng)可以不用考慮.

      1. swapness, 這個(gè)表示了 swap 分區(qū)的使用程度, 等于0時(shí)表示盡可能不用 swap, 等于100表示積極的使用 swap, 默認(rèn)是60. 這個(gè)參數(shù)取決于具體的需求.

      2. drop_caches, 這個(gè)跟cache有關(guān), 默認(rèn)是0. 設(shè)置不同的參數(shù)可以回收系統(tǒng)的 cache 和 buffers, 不過(guò)略顯粗暴(cache 和 buffer 的存在是有意義的).

      • free pagecache: sysctl -w vm.drop_caches=1

      • free dentries and inodes: sysctl -w vm.drop_caches=2

      • free pagecache, dentries and inodes: sysctl -w vm.drop_caches=3

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多