精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

malloc底層機制:brk與mmap如何選內存分配?

系統 Linux
在深入探討brk與mmap之前,我們先來明確一個概念:在 Linux 系統中,內存分配的核心系統調用主要就是brk和mmap ,它們是進程獲取內存的兩種關鍵方式,就像程序猿伸向內存的兩只手,各自有著獨特的分工和技巧。

brk 與 mmap 作為內存分配的「雙引擎」,各自擁有獨特的運行機制和適用場景。brk 通過線性擴展堆區,在小額內存分配場景中表現出輕快靈活的特點,能夠高效地滿足程序對小塊內存的頻繁需求。而 mmap 則憑借其獨立映射的特性,在大塊內存分配以及需要共享內存、文件映射的復雜場景中展現出強大的穩定性和靈活性 。理解這兩種內存分配方式的底層機制,是開發者優化程序性能、排查內存泄漏問題的關鍵。

在工程實踐中,我們可以看到各種基于 brk 和 mmap 的優化策略和內存管理技術。內存池技術通過預先分配和復用內存,減少了系統調用的次數,提高了內存分配的效率,尤其適用于高頻小額內存分配的場景 。碎片整理技術則通過定期整理內存碎片,提高了內存的利用率,減少了內存碎片化對程序性能的影響 。這些技術的應用,進一步展示了 brk 和 mmap 在實際開發中的重要性和實用性 。

一、內存分配的「雙引擎」:brk 與 mmap 核心原理

在深入探討brk與mmap之前,我們先來明確一個概念:在 Linux 系統中,內存分配的核心系統調用主要就是brk和mmap ,它們是進程獲取內存的兩種關鍵方式,就像程序猿伸向內存的兩只手,各自有著獨特的分工和技巧。接下來,就讓我們揭開它們神秘的面紗,看看它們是如何在內存的舞臺上翩翩起舞的。

1.1 brk:堆區的線性擴展引擎

brk 系統調用是進程堆內存管理的重要工具,其核心機制在于通過移動進程堆頂指針(program break)來動態擴展內存空間。進程啟動時,堆區位于數據段末端,隨著程序運行,當需要更多內存時,brk 會將堆頂指針向高地址移動,新分配的內存便緊接在已有堆內存之后,形成連續的線性區域。這一過程就好比在現有土地上進行擴建,不斷拓展可使用的空間。

圖片圖片

從內存分配的實際過程來看,brk 有著獨特的優勢和特性。首先,brk 在進行內存分配時,僅修改虛擬內存邊界,并不會立即分配物理內存。只有當進程首次訪問新分配的虛擬內存區域時,才會觸發缺頁中斷,此時操作系統才會真正分配物理內存,并建立虛擬內存與物理內存之間的映射關系。這種按需分配的策略有效地避免了內存的提前浪費,提高了內存使用效率 。

其次,brk 分配的內存是連續的,這在許多場景下都極為重要。例如,對于一些需要頻繁讀寫大塊連續數據的應用,如數據庫緩存,連續的內存空間可以顯著提高數據訪問速度,減少緩存未命中的次數,因為連續內存有利于提高緩存命中率,使得數據能夠更高效地在內存與緩存之間傳輸 。此外,glibc 的 sbrk 函數對 brk 進行了封裝,提供了更為便捷的增量分配接口。通過 sbrk,開發者可以直接指定增加或減少的內存大小,而無需手動計算新的堆頂地址,大大簡化了內存操作流程。

不過,brk 也存在一些局限性。由于其分配的內存依賴堆頂指針的移動,釋放內存時需按順序進行,即高地址的內存先釋放,低地址的內存后釋放。這就導致如果中間部分的內存被釋放,會形成內存空洞,而這些空洞在后續的內存分配中可能無法被充分利用,從而產生內存碎片化問題。隨著程序不斷地進行內存分配和釋放操作,內存碎片化可能會越來越嚴重,最終導致即使堆區還有足夠的空閑內存,但由于碎片的存在,無法滿足較大內存塊的分配需求,影響程序的正常運行。

這種分配方式有著自己獨特的特點:

  • 虛擬內存與物理內存的延遲綁定:brk僅修改虛擬內存邊界,并不會立即分配物理內存。只有當程序首次訪問這片新分配的虛擬內存時,才會觸發缺頁中斷,操作系統這時才會真正分配物理內存給進程。這就像是你先規劃好了新房間的位置(設置虛擬內存邊界),但還沒真正開始砌墻(分配物理內存),直到有人要住進去(首次訪問)才開始動工。
  • 堆區內存的順序釋放:分配的內存屬于進程堆區,在釋放的時候需要按順序來,后分配的先釋放。就好比你擴建的房間,你要拆除的時候,得從最后建的那間開始拆。
  • 封裝與增量分配:在 glibc 中,sbrk函數是brk的封裝,它提供了增量分配接口。例如,sbrk(n)會將堆頂指針移動n個字節,實現增量式的內存分配。這就像是你每次可以一小部分一小部分地擴建你的房子,非常靈活。

brk這種方式特別適合小塊內存的快速分配,比如幾 KB 到幾十 KB 的內存分配,因為它操作簡單,只需要移動一下堆頂指針就可以完成內存分配的 “規劃”,速度非常快。但它也有自己的局限性,比如容易產生內存碎片,就像你不斷地在房子后面擴建小房間,拆了又建,建了又拆,最后可能會剩下很多不規則的小塊空地(內存碎片),很難再利用起來。

1.2 mmap:虛擬空間的獨立映射器

mmap 系統調用則開辟了另一種內存分配的途徑,它在堆與棧之間的 “文件映射區” 創建獨立的內存區域。當調用 mmap 時,進程可以指定映射的長度、權限(如設置為 MAP_ANONYMOUS 表示匿名映射,不與任何文件關聯)等參數,內核會據此生成獨立的內存管理單元(vm_area_struct)。這個內存管理單元就像是一個獨立的 “小房間”,與堆區的內存管理相互獨立,擁有自己的地址空間和權限設置 。參考這篇《超硬核,基于mmap和零拷貝實現高效的內存共享

圖片圖片

mmap 的獨特優勢使其在特定場景下表現出色。一方面,mmap 支持非連續內存分配,這對于需要分配大塊內存的場景尤為重要。當程序需要申請一塊較大的內存時,mmap 可以直接在文件映射區找到合適的空閑區域進行分配,而不受堆區連續內存的限制,避免了因堆區連續擴容導致的整體膨脹和內存碎片化問題。在大數據處理、圖形渲染等需要大量內存的應用中,mmap 能夠高效地滿足內存需求,確保程序的穩定運行。

另一方面,mmap 具有零拷貝特性,特別是在文件映射場景中,它可以直接將文件內容映射到內存中,進程對文件的讀寫操作就如同對內存的讀寫一樣,減少了數據在用戶空間和內核空間之間的搬運開銷。例如,在文件傳輸過程中,傳統的 read/write 方式需要多次數據拷貝和系統調用,而 mmap 通過內存映射,讓數據直接在內存中進行處理,大大提高了數據傳輸效率,減少了 CPU 的負載 。此外,mmap 分配的內存釋放時不依賴堆區順序,通過 munmap 函數可以獨立地將內存歸還給系統,無論該內存塊在映射區域中的位置如何,都能直接釋放,這使得內存管理更加靈活,進一步減少了內存碎片化的風險。

mmap的特點也十分顯著:

  • 非連續內存分配與大塊內存支持:它支持非連續內存分配,特別適合大塊內存的分配,在大多數系統中,默認超過 128KB 的內存分配就會使用mmap。這就像你要建設一個大型工業園區,不需要在已有的城市區域里一點點拼湊,而是可以直接在郊區劃出一大塊獨立的土地來建設。
  • 零拷貝特性提升效率:mmap具有零拷貝特性,尤其是在文件映射場景中,它減少了數據搬運開銷。比如在讀取大文件時,傳統的read方式需要將數據從內核緩沖區拷貝到用戶緩沖區,而mmap可以直接將文件映射到用戶空間,進程直接訪問映射內存,就像你可以直接在工業園區里工作,而不需要把工業園區的產品先搬到家里再進行處理,大大提高了效率。像 Kafka 在 Broker 讀寫 index 文件時就用了 mmap 零復制技術,大大提升了數據處理的效率。
  • 獨立釋放避免碎片化:mmap通過munmap可以獨立釋放內存,避免了內存碎片化問題。每個通過mmap分配的內存區域就像一個獨立的小區,你可以隨時拆除(釋放)任何一個小區,而不會影響其他區域,不像brk分配的內存,釋放時受到順序限制,容易產生碎片。

1.3 brk與 mmap 二者之間區別

brk(及 sbrk)和 mmap 是操作系統提供的兩種內存分配相關的系統調用,主要區別體現在作用范圍、適用場景、內存管理方式等方面。

  • 操作的內存區域不同。brk/sbrk 僅用于調整進程堆的邊界,通過修改堆頂指針改變堆的大小;而 mmap 用于在虛擬地址空間中創建獨立的內存區域,該區域與堆、棧等現有區域不連續。
  • 適用的內存大小場景不同。brk/sbrk 適合小塊內存分配(如幾 KB 到幾十 KB),因堆內存連續,分配釋放開銷小,且釋放后可被 malloc 緩存復用;mmap 更適合大塊內存分配(通常超 128KB),能避免堆內存碎片,且釋放后直接歸還給操作系統。
  • 內存釋放與回收機制不同。brk 分配的堆內存釋放后,會進入 malloc 的空閑列表供后續復用,僅當堆頂連續空閑內存足夠大時才歸還給系統;mmap 分配的匿名內存釋放時,通過 munmap 直接歸還操作系統,不再被進程占用。
  • 內存地址連續性不同。brk 分配的內存屬于堆的一部分,地址連續;mmap 分配的內存是獨立區域,地址與堆、棧等不連續,各 mmap 區域間也可能離散。

二、核心區別:為什么 malloc 選擇「大小有別」?

通過對brk和mmap原理的剖析,我們已經了解到它們各自的特點和工作方式。接下來,讓我們深入探討它們之間的核心區別,以及為什么malloc會根據內存大小來選擇不同的底層實現機制。這就像是一個精密的儀器,不同的部件在不同的情況下發揮著最佳的作用,而malloc就像是這個儀器的智能控制系統,根據不同的 “任務”(內存分配需求)來選擇最合適的 “工具”(brk或mmap) 。

2.1 內存布局與碎片化對比

從內存布局的角度來看,brk和mmap有著顯著的區別。brk分配的內存位于堆區,是在數據段末端進行線性擴展的,就像一條不斷延伸的直線,所有分配的內存塊緊密相連,依賴堆頂指針來管理內存的邊界。這種方式在內存釋放時,必須按照分配的順序,從高地址的內存塊開始釋放。這就好比你在書架上依次擺放書籍,要拿走書籍時,也得從最后放上去的那本開始拿。如果中間釋放了某個內存塊,就會在堆區留下一個空洞,后續的內存分配如果大小不合適,就無法利用這個空洞,從而導致內存碎片化。就像書架上拿走了中間的幾本書,留下了幾個不規則的空位,很難再找到合適大小的書籍來填補。

而mmap則在文件映射區創建獨立的內存映射區域,每個區域就像一個獨立的小房間,它們之間可以是非連續的。在釋放內存時,每個區域可以獨立進行,不會受到其他區域的影響。這就好比你有多個獨立的小倉庫,你可以隨時關閉(釋放)任何一個倉庫,而不會影響其他倉庫的使用,大大降低了內存碎片化的風險。 就像你在不同的地方有多個小書架,每個書架都可以獨立管理,拿走某個書架上的書不會影響其他書架的布局,避免了出現像brk那樣的整體布局混亂(內存碎片化)問題。

對比維度

堆區(brk)

文件映射區(mmap)

內存釋放順序

順序釋放(高地址優先)

獨立釋放(任意區域)

內存碎片化程度

高(中間釋放形成空洞)

低(單區域釋放無影響)

內存分配開銷

低(僅修改指針)

中(創建映射結構)

2.2 系統調用開銷與適用場景

在系統調用開銷方面,brk和mmap也有著各自的特點。brk每次調用僅僅修改一個指針值,就像是你只需要在地圖上移動一個標記來表示新的邊界,這種操作非常簡單快捷,系統調用開銷極低,大約只需要 100 納秒。這使得它非常適合高頻、小塊內存的分配場景,比如鏈表節點的創建,這些節點通常只需要很小的內存空間,而且可能會頻繁地創建和銷毀;還有臨時緩沖區的分配,這些緩沖區在程序運行過程中臨時使用,大小通常也不大,使用brk可以快速地分配和釋放內存,提高程序的運行效率。

相比之下,mmap在創建內存映射時,需要創建vm_area_struct結構并建立復雜的映射關系,這就像是你要建立一個新的社區,需要進行詳細的規劃和建設。這種初始化過程的開銷較高,大約需要 500 納秒。但是,mmap的優勢在于它的強大功能和穩定性。它支持靈活的內存釋放方式,適合大塊內存的分配,比如緩沖區的創建,當你需要一個較大的連續內存空間來存儲大量數據時,mmap可以很好地滿足需求;在動態庫加載時,也通常會使用mmap,它可以將動態庫文件映射到進程的虛擬地址空間,實現高效的共享和調用。此外,mmap在文件映射場景中表現出色,比如數據庫索引的加載,通過mmap可以直接將索引文件映射到內存中,進程可以像訪問內存一樣快速訪問索引數據,大大提高了數據庫的查詢效率。

2.3 malloc 的「策略選擇」

在 glibc 的malloc實現中,內存分配大小與一個關鍵閾值(默認是 128KB)的比較決定了底層采用的內存分配機制。參考這篇《glibc堆內存管理:原理、機制與實戰

當分配的內存較小(小于 128KB)時,malloc會選擇走brk擴展堆區的方式。這是因為小塊內存的分配和釋放操作可能會非常頻繁,而brk的低系統調用開銷可以很好地應對這種高頻操作。同時,malloc利用空閑塊鏈表來復用內存,比如 ptmalloc 的 fastbin 機制,它會將一些小塊內存塊組織成一個快速分配鏈表,當有新的小塊內存分配請求時,優先從這個鏈表中查找合適的內存塊進行分配,避免了頻繁的系統調用,進一步提高了分配效率。這就像是你有一個小工具盒,里面有一些常用的小工具,每次需要使用小工具時,你可以直接從工具盒里快速找到,而不需要每次都去大倉庫(系統內存)里尋找。

當分配的內存較大(大于等于 128KB)時,malloc會直接調用mmap來創建獨立的內存映射。這是因為大塊內存的分配如果使用brk,很容易導致堆區的碎片化,影響后續的內存分配效率。而mmap的獨立內存管理方式可以避免這個問題,雖然它的初始化開銷較高,但對于大塊內存的一次性分配來說,這點開銷是可以接受的。這就好比你要建造一座大型建筑,雖然前期的規劃和準備工作(初始化開銷)比較繁瑣,但建成后可以獨立使用,不會影響其他區域,也不會因為后續的一些小改動(內存釋放和再分配)而導致整體結構的混亂(內存碎片化)。

三、實戰指南:如何正確使用 brk 與 mmap?

在了解了brk和mmap的原理以及它們在malloc中的應用之后,接下來我們進入實戰環節,看看在實際編程中如何正確地使用它們,以及在使用過程中有哪些性能優化技巧和常見陷阱需要注意。這就像是我們學會了理論知識之后,要親自上手實踐,在實踐中掌握這些內存分配工具的使用技巧,讓它們為我們的程序高效運行保駕護航。

3.1 基礎 API 使用示例

(1)brk/sbrk 調用

在 C 語言中,brk和sbrk函數用于操作堆內存。brk函數直接設置堆頂指針,而sbrk函數則是在當前堆頂指針的基礎上進行增量調整。下面是一個簡單的示例,展示了如何使用sbrk來分配和釋放內存:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main() {
    // 使用sbrk分配1024字節內存
    char *p = (char *)sbrk(1024);
    if (p == (void *)-1) {
        perror("sbrk");
        return 1;
    }

    // 使用分配的內存
    for (int i = 0; i < 1024; i++) {
        p[i] = i;
    }

    // 輸出內存中的前10個字節
    for (int i = 0; i < 10; i++) {
        printf("%d ", p[i]);
    }
    printf("\n");

    // 使用sbrk釋放內存(將堆頂指針回退1024字節)
    if (sbrk(-1024) == (void *)-1) {
        perror("sbrk");
        return 1;
    }

    return 0;
}

在這個示例中,我們首先使用sbrk(1024)分配了 1024 字節的內存,然后對這塊內存進行了初始化操作,最后通過sbrk(-1024)將堆頂指針回退 1024 字節,實現了內存的釋放。需要注意的是,在實際應用中,直接使用brk和sbrk進行內存管理的情況比較少見,因為它們的操作相對底層,容易出錯,通常會使用更高級的內存分配函數,如malloc和free 。

(2)mmap/munmap 調用

mmap函數用于創建內存映射,munmap函數則用于取消內存映射。下面是一個使用mmap映射文件的示例:

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main() {
    int fd;
    char *file_content;
    struct stat file_stat;

    // 打開文件
    fd = open("test.txt", O_RDWR);
    if (fd == -1) {
        perror("open");
        return 1;
    }

    // 獲取文件大小
    if (fstat(fd, &file_stat) == -1) {
        perror("fstat");
        close(fd);
        return 1;
    }

    // 使用mmap映射文件
    file_content = (char *)mmap(0, file_stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (file_content == MAP_FAILED) {
        perror("mmap");
        close(fd);
        return 1;
    }

    // 輸出文件內容
    printf("File content:\n%s\n", file_content);

    // 修改文件內容
    strcpy(file_content, "This is a modified content.");
    printf("Modified file content:\n%s\n", file_content);

    // 取消映射
    if (munmap(file_content, file_stat.st_size) == -1) {
        perror("munmap");
    }

    // 關閉文件
    close(fd);

    return 0;
}

在這個示例中,我們首先打開一個文件,獲取其大小,然后使用mmap將文件內容映射到內存中。通過返回的指針,我們可以像訪問普通內存一樣訪問文件內容,對其進行讀取和修改。最后,使用munmap取消內存映射,并關閉文件描述符。這個示例展示了mmap在文件映射場景中的基本用法,通過這種方式,可以大大提高文件的讀寫效率,尤其是在處理大文件時。

3.2 性能優化技巧

在實際使用brk和mmap時,合理的性能優化可以顯著提升程序的運行效率。以下是一些常見的性能優化技巧:

小塊內存復用:對于頻繁分配釋放的小塊內存,如網絡請求臨時數據,直接調用brk會導致大量的系統調用開銷。此時,改用內存池(如 tcmalloc 的 thread - local cache)是一個很好的選擇。內存池通過預先分配一塊較大的內存,然后在內部維護一個或多個鏈表,用于快速分配和回收小塊內存。這樣可以減少系統調用的次數,提高內存分配和釋放的效率。例如,在一個高并發的網絡服務器中,每個網絡請求可能只需要幾 KB 的內存來存儲臨時數據,如果每次都直接調用brk來分配內存,會導致大量的系統調用開銷,影響服務器的性能。而使用內存池,就可以在內存池中快速分配和回收這些小塊內存,避免了頻繁的系統調用。

大塊內存對齊:在使用mmap分配大塊內存時,可以指定MAP_POPULATE標志來預分配物理內存。這樣可以減少后續訪問這些區域時觸發缺頁中斷的可能性,提高訪問速度。另外,利用大頁(Huge Pages)也是一種優化方式。大頁可以減少頁表的大小,降低 TLB(Translation Lookaside Buffer)缺失的概率,從而提升內存訪問效率。在一些對內存訪問性能要求極高的應用中,如數據庫系統,經常會使用大頁來提高內存訪問速度。例如,在 MySQL 數據庫中,可以通過配置參數來啟用大頁,提高數據庫的性能。

碎片整理:對于brk分配的內存,可以通過mallopt(M_TRIM_THRESHOLD, 0)強制brk釋放超過閾值的空閑內存,減少內存碎片的產生。對于mmap分配的內存,可以使用madvise函數對內存區域進行預取 / 丟棄優化。例如,當應用程序知道將來會使用某些數據時,可以通過madvise建議操作系統提前加載這些數據到內存中,提高數據訪問的效率;當應用程序不再需要某些數據時,可以通過madvise告知內核釋放內存,優化內存使用。在一個視頻播放應用中,在播放視頻前,可以通過madvise預取視頻數據,避免播放過程中出現卡頓;在視頻播放結束后,可以通過madvise釋放不再需要的內存,提高系統的內存利用率。

3.3 常見陷阱與避坑

在使用brk和mmap的過程中,也存在一些常見的陷阱,如果不注意,可能會導致程序出現內存泄漏、性能下降等問題。以下是一些常見的陷阱及避免方法:

brk 的「釋放限制」:在使用brk釋放堆內存時,只能回退到最近一次分配的高地址,若中間有未釋放塊則無法縮減。例如,先進行 A 分配,再進行 B 分配,然后釋放 A,此時會導致內存空洞,只有等 B 釋放后才能整體回收。這就像是你在書架上依次放書,先放了 A 書,再放了 B 書,當你想拿走 A 書時,如果 B 書還在,就無法直接拿走 A 書所在的那一層空間,必須先拿走 B 書,才能真正釋放 A 書占用的空間。為了避免這種情況,在設計內存分配策略時,需要充分考慮內存的釋放順序,盡量避免出現中間有未釋放塊的情況。

mmap 的「泄漏風險」:如果忘記調用munmap取消內存映射,會導致虛擬內存泄漏。雖然這種泄漏不會占用物理內存,但會消耗地址空間,最終可能導致進程無法再分配新的內存。可以通過pmap pid命令查看進程的映射情況,排查是否存在未釋放的內存映射。這就像是你租了一間房子,住完后卻忘記退房,雖然房子里沒有人住,但別人也無法再租用這間房子,造成了資源的浪費。在編寫程序時,一定要確保在不再需要內存映射時,及時調用munmap進行釋放。

權限控制:使用mmap時,可以設置PROT_NONE權限來創建一個保護區域,捕獲非法訪問,如緩沖區溢出。但是,這需要配合信號處理(SIGSEGV)使用,當發生非法訪問時,系統會發送SIGSEGV信號,程序可以通過捕獲這個信號來進行相應的處理,如記錄錯誤日志、進行錯誤恢復等。這就像是你在房子周圍設置了一圈警戒線,當有人非法闖入時,就會觸發警報,你可以根據警報進行相應的處理。在使用mmap時,合理設置權限和信號處理,可以提高程序的安全性和穩定性。

四、內存分配之道

4.1 操作系統的「平衡之道」

brk與mmap的設計精妙地體現了操作系統在「效率」與「靈活」之間的權衡智慧。brk通過簡單地移動堆頂指針來分配內存,這種方式雖然在靈活性上有所欠缺,例如它只能分配連續的內存空間,釋放內存時也受到嚴格的順序限制,但它卻在高頻內存分配操作中展現出了極高的效率。就像在一個小型工廠里,所有的生產流程都非常簡單直接,雖然不能生產出非常復雜多樣的產品,但是對于一些常規的、大量需求的簡單產品,卻能以最快的速度生產出來。這種特性使得brk特別適合那些對內存分配速度要求極高,且內存需求相對較小且連續的場景,比如在一個頻繁創建和銷毀小對象的程序中,brk能夠快速地為這些小對象分配內存,保證程序的高效運行。

而mmap則走向了另一個方向,它放棄了單一連續空間的限制,允許創建獨立的內存映射區域。這就好比一個大型的綜合性工廠,它可以生產各種復雜的、多樣化的產品,每個產品的生產流程都可以獨立進行。mmap的這種特性賦予了它強大的靈活性,它可以實現內存的獨立管理和共享,特別適合那些對內存管理靈活性要求較高,且內存需求較大的場景,比如在跨進程通信中,mmap可以創建共享內存區域,讓多個進程能夠高效地共享數據;在處理大文件時,mmap可以將文件直接映射到內存中,實現高效的文件讀寫操作。

這種在不同維度上的權衡與設計,不僅僅體現在內存分配領域,在整個操作系統的設計中都有著廣泛的體現。以 TCP/IP 協議棧為例,BSD socket 和 raw socket 就是這種分層設計思想的典型體現。BSD socket 為應用層提供了一個相對高層、抽象的接口,它隱藏了底層網絡協議的許多細節,使得應用程序可以方便快捷地進行網絡通信,就像使用一個已經組裝好的工具,只需要簡單操作就能完成任務,這體現了對效率的追求。而 raw socket 則允許開發者直接訪問底層的網絡協議,能夠對網絡數據包進行更加精細的控制,雖然使用起來相對復雜,但卻提供了極大的靈活性,適用于一些對網絡通信有特殊需求的場景,比如網絡協議分析工具的開發。

同樣,在文件系統的設計中,ext4 和 f2fs 也展現了類似的分層設計思想。ext4 是一種廣泛使用的文件系統,它在設計上注重兼容性和穩定性,采用了傳統的文件系統結構,對于大多數常規的文件存儲和訪問需求,都能提供高效的支持,這體現了對效率的保障。而 f2fs 則是一種專門為閃存設備設計的文件系統,它針對閃存的特性進行了優化,采用了更加靈活的結構,能夠更好地適應閃存的讀寫特點,提高閃存設備的使用壽命和性能,這體現了對特定場景下靈活性的追求。

4.2 現代內存分配器的「融合創新」

以 glibc 的 ptmalloc、Google 的 tcmalloc 為代表的現代內存分配器,巧妙地采用了「brk + mmap 混合策略」,將brk和mmap的優勢發揮到了極致。

對于小對象(一般小于 64KB) ,這些分配器通常會利用線程本地緩存來進行分配。以 TCMalloc 的 thread cache 為例,每個線程都有自己獨立的緩存,當線程需要分配小對象時,可以直接從自己的緩存中獲取內存,避免了鎖競爭。這就好比每個員工都有自己的小工具盒,當需要使用小工具時,直接從自己的工具盒里拿取,不需要和其他員工爭搶大倉庫里的工具,大大提高了分配的效率。

當面對中對象(64KB - 128KB)時,分配器會通過brk從堆區分配內存。在這個過程中,分配器會利用空閑塊合并的技術,將相鄰的空閑內存塊合并成更大的內存塊,減少內存碎片的產生。這就像是在整理倉庫時,將相鄰的小空位合并成一個大空位,以便更好地利用空間。例如,ptmalloc 會維護不同大小的空閑塊鏈表,當有新的內存分配請求時,會首先在合適的鏈表中查找是否有可用的空閑塊,如果有則直接分配,否則會嘗試合并相鄰的空閑塊來滿足請求。

而對于大對象(大于 128KB),分配器會直接使用mmap來分配內存。由于大對象的內存需求較大,如果使用brk分配,很容易導致堆區的碎片化,影響后續的內存分配效率。而mmap的獨立內存管理方式可以避免這個問題,雖然它的初始化開銷較高,但對于大對象的一次性分配來說,這點開銷是可以接受的。這就好比建造大型建筑,雖然前期的規劃和準備工作比較繁瑣,但建成后可以獨立使用,不會影響其他區域,也不會因為后續的一些小改動而導致整體結構的混亂。

這種混合策略的設計,不僅兼顧了性能與穩定性,還將底層系統調用的細節封裝起來,向上層應用提供了統一的malloc/free接口。應用程序在進行內存分配時,不需要關心底層到底是使用brk還是mmap,只需要調用malloc函數即可,這大大簡化了開發者的工作,同時也提高了程序的可移植性和可維護性。

4.3 開發者的「選擇原則」

在實際的開發過程中,開發者需要根據不同的業務場景和需求,合理地選擇內存分配方式。

優先使用標準庫接口:在大多數情況下,開發者應該優先使用標準庫提供的malloc/free接口。這些接口經過了大量的測試和優化,能夠根據內存分配的大小自動選擇合適的底層實現機制(brk或mmap) 。除非開發者有特殊的需求,例如需要實現自定義的內存分配器,如在游戲引擎中,為了提高內存管理的效率和性能,常常會實現自己的內存池,否則直接使用標準庫接口是最簡便、最安全的選擇。

關注業務場景:業務場景是選擇內存分配方式的重要依據。對于高頻小塊內存的分配場景,例如在一個網絡服務器中,每個網絡請求可能只需要幾 KB 的內存來存儲臨時數據,這種情況下應該盡量避免使用mmap,因為mmap的高開銷會嚴重影響系統的性能,而brk則是更好的選擇。相反,對于大塊內存的分配或者需要共享內存的場景,比如在跨進程通信中,需要創建共享內存區域來實現數據的共享,這時就應該優先使用mmap,因為它能夠提供獨立的內存管理和共享能力,滿足業務的需求。

性能 profiling:為了確保內存分配的效率,開發者可以通過性能分析工具來監控系統調用的頻率。例如,可以使用perf trace -e mmap或strace -f -e brk,mmap命令來監控mmap和brk系統調用的頻率,從而定位到內存分配的低效點。通過分析這些數據,開發者可以針對性地優化內存分配策略,提高程序的性能。比如,如果發現某個模塊中頻繁地調用mmap來分配小塊內存,就可以考慮優化該模塊的內存分配方式,改為使用brk或者內存池,以降低系統調用的開銷,提高程序的運行效率。

責任編輯:武曉燕 來源: 深度Linux
相關推薦

2023-12-27 13:55:00

C++內存分配機制new

2022-03-18 22:39:57

動態內存malloc

2024-11-07 09:37:46

2016-11-07 09:02:02

Malloc內存syscall

2024-10-11 10:00:20

2025-06-05 03:10:00

mmapmalloc共享內存

2025-03-05 00:49:00

Win32源碼malloc

2025-05-29 03:20:00

2011-05-26 15:41:25

java虛擬機

2025-06-19 01:00:00

2024-09-03 09:15:37

2021-04-16 07:32:34

推薦算法機制

2019-07-03 10:29:59

JavaScript算法程序員

2025-09-12 05:00:00

2013-10-12 13:01:51

Linux運維內存管理

2015-11-16 11:17:30

PHP底層運行機制原理

2009-06-03 15:52:34

堆內存棧內存Java內存分配

2011-04-25 17:15:39

MongodbMMAP

2023-03-01 10:37:51

2019-06-24 19:00:09

JavaScript內存泄漏垃圾回收
點贊
收藏

51CTO技術棧公眾號

日韩av一二三四| 韩日午夜在线资源一区二区 | av一区在线| 中文一区一区三区高中清不卡| 成人h猎奇视频网站| 久久久久久久伊人| 欧美伦理在线视频| 日韩欧美一级二级三级久久久| 日韩av综合在线观看| wwwww在线观看免费视频| 国产精品一区二区在线观看不卡 | 国产a亚洲精品| 一区二区三区四区蜜桃| 欧美日韩国产综合在线| 96日本xxxxxⅹxxx17| 亚洲国产精品第一区二区| 亚洲欧美另类自拍| 一级全黄裸体片| 国产第一亚洲| 欧美午夜电影在线| 欧美精品在欧美一区二区| 高清在线观看av| www.久久精品| 99久久精品无码一区二区毛片 | 久久精品色妇熟妇丰满人妻| 动漫3d精品一区二区三区乱码| 欧美午夜片在线看| jizzjizz国产精品喷水| av电影免费在线观看| 国产午夜亚洲精品理论片色戒 | 在线免费观看av网| 欧美大片免费观看网址| 亚洲国产sm捆绑调教视频| 中文网丁香综合网| 草草影院在线观看| 26uuu成人网一区二区三区| 51国偷自产一区二区三区| 波多野结衣在线电影| 国产精品主播| 午夜精品一区二区三区在线播放| 91麻豆精品成人一区二区| 欧美综合一区| 一道本无吗dⅴd在线播放一区| 中文字幕天堂网| 99精品中文字幕在线不卡 | 老熟女高潮一区二区三区| 亚洲热av色在线播放| 欧美日韩一区二区三区不卡| www.欧美日本| 网友自拍亚洲| 色天天综合色天天久久| 国产深夜男女无套内射| brazzers在线观看| 亚洲成人动漫精品| 国产色一区二区三区| xxxx视频在线| 午夜影院在线观看欧美| www.av中文字幕| www在线观看黄色| 亚洲国产一二三| av在线观看地址| av资源新版天堂在线| 天天综合日日夜夜精品| 亚洲熟妇av日韩熟妇在线| 蜜桃麻豆影像在线观看| 日韩欧美成人区| 女性隐私黄www网站视频| 国产精品专区免费| 欧美亚州韩日在线看免费版国语版| 无码日韩人妻精品久久蜜桃| 九九久久国产| 日韩欧美一二三四区| 高清中文字幕mv的电影| 亚洲精品播放| 中文字幕亚洲欧美日韩高清| 黄色录像一级片| 欧美视频在线观看| 538国产精品一区二区免费视频| 中文字幕在线播| 乱一区二区av| caoporn国产精品免费公开| 亚洲欧美另类一区| av不卡免费电影| 色一情一乱一伦一区二区三区丨| 日本在线观看| 亚洲国产精品综合小说图片区| 亚洲熟妇国产熟妇肥婆| 本网站久久精品| 日韩久久久精品| 亚洲午夜福利在线观看| 99精品小视频| 午夜精品久久久99热福利| 69视频免费看| 国产成人亚洲精品狼色在线 | 99精品视频精品精品视频| 欧美激情精品久久久久久久变态| 久久久久久少妇| 久久69国产一区二区蜜臀| 国产精品一区在线播放| 粉嫩av在线播放| 一区二区三区精品久久久| 可以在线看的黄色网址| 日韩一区二区三区在线看| 精品香蕉在线观看视频一| 欧美h片在线观看| 亚洲在线成人| 亚洲自拍偷拍色图| 国产在线视频网| 亚洲成人综合在线| 制服丝袜综合网| 亚州精品视频| 欧美伦理91i| 中文字幕男人天堂| 99精品久久免费看蜜臀剧情介绍| 一区一区视频| 中文字幕在线看片| 日韩精品资源二区在线| 91麻豆制片厂| 亚洲综合99| 国产精品对白刺激久久久| 日韩av中文| 色综合久久88色综合天天6 | 国产精品毛片av| 久久久91精品国产一区不卡| 日韩精品成人免费观看视频| 成人白浆超碰人人人人| 日韩不卡一二区| 欧美高清xxx| 亚洲欧美中文日韩在线v日本| 一区二区三区免费高清视频| 久久99精品国产.久久久久| 欧美日韩成人一区二区三区| 僵尸再翻生在线观看| 欧美v亚洲v综合ⅴ国产v| 色老板免费视频| 另类中文字幕网| 日韩久久不卡| 二吊插入一穴一区二区| 亚洲乱码国产乱码精品精天堂| 国产精彩视频在线| 国产91精品免费| 9l视频自拍9l视频自拍| 日韩一级视频| 综合网日日天干夜夜久久| 黄色网址中文字幕| 久久亚洲二区三区| 怡红院av亚洲一区二区三区h| 精品淫伦v久久水蜜桃| 97精品国产aⅴ7777| 无套内谢的新婚少妇国语播放| 亚洲在线视频一区| 欧美性生交xxxxx| 激情久久一区| 狠狠色狠狠色综合人人| f2c人成在线观看免费视频| 精品国产一区二区三区忘忧草| 国产中文字幕免费| 成人av网站在线观看免费| 男人添女荫道口图片| 卡通动漫国产精品| 欧美综合在线观看| 黄色的视频在线免费观看| 欧美在线小视频| 日韩在线一卡二卡| 国产成人精品亚洲日本在线桃色| 成年人视频网站免费| 老牛影视av一区二区在线观看 | 巨大黑人极品videos精品| 日韩中文字幕在线视频| 国产熟女一区二区丰满| 亚洲一区二区三区三| 中文字幕 亚洲一区| 亚洲免费一区二区| 亚洲国产激情一区二区三区| 精品国产一区二区三区性色av| 色综合久久88| 日韩av免费观影| 欧美日韩成人综合| 久久久久免费看| 久久亚洲一区二区三区四区| 性生活免费在线观看| 欧美激情第10页| 最近中文字幕av| 国产成人免费看| 免费一级欧美片在线播放| 欧美综合激情| 色综合视频一区二区三区44| 欧美国产日韩一区二区在线观看| 性猛交xxxx| 欧美日韩一级二级| 久久久无码一区二区三区| 久久―日本道色综合久久| 中文字幕永久有效| 99亚洲伊人久久精品影院红桃| 热re99久久精品国产99热| 国产精品一区二区精品| 欧洲一区二区视频| 精品视频在线一区二区| 日韩成人在线视频| 国产精品久久久久久久久毛片| 亚洲成av人影院| 999精品在线视频| 91小视频免费看| 久久久精品视频国产| 久久免费黄色| 久久99中文字幕| 91成人精品| 日韩女优中文字幕| 久久成人福利| 91久久精品www人人做人人爽| 向日葵视频成人app网址| 久久欧美在线电影| 麻豆传媒在线观看| 亚洲午夜久久久久久久| 丰满岳乱妇国产精品一区| 欧美日韩一级二级| 久久久久久在线观看| 亚洲一二三四在线| 老熟妻内射精品一区| 国产人久久人人人人爽| 国产熟女高潮一区二区三区| 国产麻豆精品theporn| 午夜视频你懂的| 久久精品麻豆| 日本中文字幕网址| 国内精品久久久久久久影视蜜臀 | 欧美一级淫片免费视频魅影视频| 欧美在线观看一二区| 天天干天天干天天| 婷婷综合另类小说色区| 男人与禽猛交狂配| 亚洲色图清纯唯美| 永久免费看片视频教学| 亚洲国产精品高清| 日韩女同一区二区三区| 久久久精品2019中文字幕之3| 香港三日本8a三级少妇三级99| 国产成人免费xxxxxxxx| 手机在线观看日韩av| 国产一区二区调教| 免费成人黄色大片| 精品一区二区三区的国产在线播放| 免费在线观看的毛片| 天堂精品中文字幕在线| 久草资源站在线观看| 亚洲一区亚洲| 国产自偷自偷免费一区| 天堂久久久久va久久久久| 日韩视频免费在线播放| 日韩影院精彩在线| 亚洲福利精品视频| 久久电影网站中文字幕| 国产精品v日韩精品v在线观看| 奇米四色…亚洲| 最新国产黄色网址| 国产在线日韩欧美| 国产xxx在线观看| 福利一区二区在线| 亚洲国产综合视频| 久久久综合精品| 中文字幕黄色网址| 中文字幕一区二区三区av| 午夜爽爽爽男女免费观看| 亚洲视频每日更新| 国产亚洲小视频| 午夜视频久久久久久| av大片免费观看| 欧亚洲嫩模精品一区三区| 在线观看国产一区二区三区| 欧美一级在线免费| 婷婷视频在线观看| 亚洲欧洲一区二区三区在线观看| yiren22亚洲综合伊人22| 久久精品99久久香蕉国产色戒| 综合图区亚洲| 91av视频在线免费观看| 97成人超碰| 成人自拍爱视频| 国产成人影院| 玖玖精品在线视频| 亚洲欧洲综合| 欧美日韩在线成人| 国产成人av电影在线播放| 极品白嫩丰满美女无套| 一色屋精品亚洲香蕉网站| 国产一二三四在线| 欧美三级一区二区| 丰满人妻妇伦又伦精品国产| 亚洲女人被黑人巨大进入al| 日本三级视频在线播放| 久久久久久97| 亚洲成人va| 国产精品久久久久久久天堂第1集| 欧美美女在线观看| 无码毛片aaa在线| 午夜一级久久| 黑人巨大猛交丰满少妇| 2020国产精品自拍| 国产精品久久久精品四季影院| 欧美天堂在线观看| 国产av无码专区亚洲a∨毛片| 国产丝袜精品第一页| 在线你懂的视频| 国产精品福利在线观看| 国产精品18hdxxxⅹ在线| 亚洲春色在线视频| 国产精品一国产精品k频道56| 国产不卡的av| 国产拍揄自揄精品视频麻豆| 曰本女人与公拘交酡| 色综合一区二区| 亚洲xxxx天美| www.亚洲男人天堂| 日韩精品一区二区三区| 成人av资源| 国产精品久久久久无码av| 欧美性大战久久久久xxx| 国产乱码精品一区二区三区av| 国产精品一二三区在线观看| 亚洲一区中文在线| 在线观看黄色网| 一级做a爰片久久毛片美女图片| 老牛影视精品| 国产精品乱子乱xxxx| 亚洲一级淫片| 欧美成人高潮一二区在线看| 国产在线精品不卡| 美女网站视频色| 在线观看一区二区视频| 先锋av资源站| 欧美黑人视频一区| 欧美电影院免费观看| 一本一本a久久| 美女国产一区二区三区| 亚洲区自拍偷拍| 色老头久久综合| 欧美色视频免费| 青草成人免费视频| 亚洲美女15p| 777米奇影视第四色| 91视频在线观看免费| 欧美三级韩国三级日本三斤在线观看| 精品少妇一区二区三区在线播放| 成码无人av片在线观看网站| 成人精品久久av网站| 99热国内精品永久免费观看| 91国内在线播放| 亚洲视频一区二区在线| 99在线无码精品入口| 久久91精品国产| 在线视频亚洲欧美中文| 分分操这里只有精品| 99精品视频在线观看免费| 中文字幕在线字幕中文| 日韩电影中文 亚洲精品乱码| 狼人综合视频| 日韩免费中文专区| 久久成人av少妇免费| 福利所第一导航| 精品少妇一区二区三区日产乱码 | 成人国产精品一区| 亚洲91视频| 日本人妻一区二区三区| 性做久久久久久免费观看欧美| 午夜在线视频免费| 国产精品久久久久久久一区探花| 日韩欧美精品| 青娱乐国产精品视频| 亚洲第一激情av| 美女毛片在线看| 成人激情黄色网| 一区在线免费观看| 亚洲国产第一区| 欧美性受xxxx黑人xyx性爽| 老司机福利在线视频| 国产日韩欧美综合精品| 亚洲女人av| 亚洲区一区二区三| 亚洲国产精品人人爽夜夜爽| 欧美成人资源| 日韩视频 中文字幕| 99re这里只有精品首页| 中文字幕第一页在线播放| 欧美精品在线免费观看| 偷拍视屏一区| 最新免费av网址| 天天综合网天天综合色| av资源网在线观看| 草莓视频一区| 日韩va欧美va亚洲va久久| 久久久久久久久精| 一区二区三区高清国产| 亚洲日本一区二区三区在线| 青青草原av在线播放| 亚洲女子a中天字幕| 青青草在线免费观看| 亚洲一区二区三区乱码aⅴ| 亚洲一区不卡| www青青草原| 伊人久久久久久久久久久久久|