1审残、下載和編譯
源碼下載:https://www.gnu.org/software/libc/
下載后解壓:tar zxvf glibc-2.23.tar.gz?
(原來這里下載了glibc-2.2.3.tar.gz万搔,一個符號點之差歌憨,導(dǎo)致編譯了半天不成功,各種錯誤)
$ tar zxvf glibc-2.23.tar.gz?
$ mkdir?glibc-build bin
設(shè)置環(huán)境變量bashrc
?cat bashrc?
export PATH=$PATH:/home/xxxx/mini_ctc_3.3/toolchain/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/
export PATH=$PATH:/home/xxxx/yodaos/openwrt/staging_dir/toolchain-arm_cortex-a7+neon_gcc-5.3.0_glibc-2.22_eabi/bin/
export CROSS_COMPILE=aarch64-linux-gnu-
export STAGING_DIR=/home/chenguolong/yodaos/openwrt/staging_dir/target-arm_cortex-a7+neon_glibc-2.22_eabi/
#export CROSS_COMPILE=arm-openwrt-linux-gnueabi-
export CC=${CROSS_COMPILE}gcc
export CPP=${CROSS_COMPILE}cppc
export CXX=${CROSS_COMPILE}g++
export LD=${CROSS_COMPILE}ld
export AR=${CROSS_COMPILE}ar
export STRIP=${CROSS_COMPILE}strip
export CFLAGS="-Wno-error=implicit-function-declaration -Wno-error=parentheses -O2"
export CMAKE_C_COMPILER=${CROSS_COMPILE}gcc
$ source bashrc
開始編譯
$ cd?glibc-build
$/home/xxxx/tmp/tools/glibc-2.23/configure --prefix=/home/chenguolong/tmp/tools/bin/ --host=aarch64-linux-gnu --disable-multilib libc_cv_forced_unwind=yes libc_cv_ssp=no libc_cv_ssp_strong=no
如果需要靜態(tài)編譯
$ ./configure CFLAGS="-static" ....
$ make LDFLAGS="-all-static"
其實編譯開源軟件都一樣惶翻,--prefix即為install目錄蝶溶,--host為編譯程序的二進(jìn)制文件執(zhí)行的主機(jī)
build:執(zhí)行代碼編譯的主機(jī),正常的話就是你的主機(jī)系統(tǒng)俱济。這個參數(shù)一般由config.guess來猜就可以。當(dāng)然自己指定也可以钙勃。
host:編譯出來的二進(jìn)制程序所執(zhí)行的主機(jī)蛛碌,因為絕大多數(shù)是如果本機(jī)編譯,本機(jī)執(zhí)行辖源。所以這個值就等于build左医。只有交叉編譯的時候(也就是本機(jī)編譯,其他系統(tǒng)機(jī)器執(zhí)行)才會build和host不同同木。用host指定運行主機(jī)。
target:這個選項只有在建立交叉編譯環(huán)境的時候用到跛十,正常編譯和交叉編譯都不會用到彤路。他用build主機(jī)上的編譯器,編譯一個新的編譯器(binutils, gcc,gdb等)芥映,這個新的編譯器將來編譯出來的其他程序?qū)⑦\行在target指定的系統(tǒng)上洲尊。
$ make -j32 && make install
2、Glibc即ptmalloc內(nèi)存管理設(shè)計假設(shè)
Ptmalloc 在設(shè)計時折中了高效率奈偏,高空間利用率坞嘀,高可用性等設(shè)計目標(biāo)。在其實現(xiàn)代碼中惊来,隱藏著內(nèi)存管理中的一些設(shè)計假設(shè)丽涩,由于某些設(shè)計假設(shè),導(dǎo)致了在某些情況下 ptmalloc 的行為很詭異。這些設(shè)計假設(shè)包括:
1. 具有長生命周期的大內(nèi)存分配使用 mmap矢渊。
2. 特別大的內(nèi)存分配總是使用 mmap继准。
3. 具有短生命周期的內(nèi)存分配使用 brk,因為用 mmap 映射匿名頁矮男,當(dāng)發(fā)生缺頁異常時移必,linux 內(nèi)核為缺頁分配一個新物理頁,并將該物理頁清 0毡鉴,一個 mmap 的內(nèi)存塊需要映射多個物理頁崔泵,導(dǎo)致多次清 0 操作,很浪費系統(tǒng)資源猪瞬,所以引入了 mmap分配閾值動態(tài)調(diào)整機(jī)制憎瘸,保證在必要的情況下才使用 mmap 分配內(nèi)存。
4. 盡量只緩存臨時使用的空閑小內(nèi)存塊撑螺,對大內(nèi)存塊或是長生命周期的大內(nèi)存塊在釋放時都直接歸還給操作系統(tǒng)含思。
5. 對空閑的小內(nèi)存塊只會在 malloc 和 free 的時候進(jìn)行合并,free 時空閑內(nèi)存塊可能放入 pool 中甘晤,不一定歸還給操作系統(tǒng)含潘。
6. 收縮堆的條件是當(dāng)前 free 的塊大小加上前后能合并 chunk 的大小大于 64KB、线婚,并且堆頂?shù)拇笮∵_(dá)到閾值遏弱,才有可能收縮堆,把堆最頂端的空閑內(nèi)存返回給操作系統(tǒng)塞弊。
7. 需要保持長期存儲的程序不適合用 ptmalloc 來管理內(nèi)存漱逸。
8. 為了支持多線程,多個線程可以從同一個分配區(qū)(arena)中分配內(nèi)存游沿,ptmalloc假設(shè)線程 A 釋放掉一塊內(nèi)存后饰抒,線程 B 會申請類似大小的內(nèi)存,但是 A 釋放的內(nèi)存跟 B 需要的內(nèi)存不一定完全相等诀黍,可能有一個小的誤差袋坑,就需要不停地對內(nèi)存塊作切割和合并,這個過程中可能產(chǎn)生內(nèi)存碎片眯勾。
總結(jié):
大塊內(nèi)存用mmap枣宫,耗時耗cpu
小塊內(nèi)存用malloc(brk),申請內(nèi)存時并非立即真申請吃环,釋放時并非真釋放
3也颤、GLIBC 重要結(jié)構(gòu)體和函數(shù)
chunk:
bins
fast bins 快速查找的chunk
unsort bin 釋放后規(guī)整
top chunk?
Main_arena??主分配區(qū),有且只有一個
non_main_arena 非主分配區(qū)郁轻,多個翅娶,多線程競爭使用
4、glibc 內(nèi)存暴增原因
1故觅、后分配的內(nèi)存先釋放厂庇,因為 ptmalloc 收縮內(nèi)存是從 top chunk 開始,如果與 top chunk 相
鄰的 chunk 不能釋放输吏,top chunk 以下的 chunk 都無法釋放权旷。
2. Ptmalloc 不適合用于管理長生命周期的內(nèi)存,特別是持續(xù)不定期分配和釋放長生命周期
的內(nèi)存贯溅,這將導(dǎo)致 ptmalloc 內(nèi)存暴增拄氯。如果要用 ptmalloc 分配長周期內(nèi)存,在 32 位系
統(tǒng)上它浅,分配的內(nèi)存塊最好大于 1MB译柏,64 位系統(tǒng)上,分配的內(nèi)存塊大小大于 32MB姐霍。這是
由于 ptmalloc 默認(rèn)開啟 mmap 分配閾值動態(tài)調(diào)整功能鄙麦,1MB 是 32 位系統(tǒng) mmap 分配閾
值的最大值,32MB 是 64 位系統(tǒng) mmap 分配閾值的最大值镊折,這樣可以保證 ptmalloc 分配
的內(nèi)存一定是從 mmap 映射區(qū)域分配的胯府,當(dāng) free 時,ptmalloc 會直接把該內(nèi)存返回給操
作系統(tǒng)恨胚,避免了被 ptmalloc 緩存骂因。
3. 不要關(guān)閉 ptmalloc 的 mmap 分配閾值動態(tài)調(diào)整機(jī)制,因為這種機(jī)制保證了短生命周期的
內(nèi)存分配盡量從 ptmalloc 緩存的內(nèi)存 chunk 中分配赃泡,更高效寒波,浪費更少的內(nèi)存。如果關(guān)
閉了該機(jī)制升熊,對大于 128KB 的內(nèi)存分配就會使用系統(tǒng)調(diào)用 mmap 向操作系統(tǒng)分配內(nèi)存俄烁,
使用系統(tǒng)調(diào)用分配內(nèi)存一般會比從 ptmalloc 緩存的 chunk 中分配內(nèi)存慢,特別是在多線
程同時分配大內(nèi)存塊時级野,操作系統(tǒng)會串行調(diào)用 mmap()页屠,并為發(fā)生缺頁異常的頁加載新
物理頁時,默認(rèn)強(qiáng)制清 0勺阐。頻繁使用 mmap 向操作系統(tǒng)分配內(nèi)存是相當(dāng)?shù)托У摹J褂?/p>
mmap 分配的內(nèi)存只適合長生命周期的大內(nèi)存塊矛双。
4. 多線程分階段執(zhí)行的程序不適合用 ptmalloc渊抽,這種程序的內(nèi)存更適合用內(nèi)存池管理,就
像 Appach 那樣议忽,每個連接請求處理分為多個階段懒闷,每個階段都有自己的內(nèi)存池,每個
階段完成后,將相關(guān)的內(nèi)存就返回給相關(guān)的內(nèi)存池愤估。Google 的許多應(yīng)用也是分階段執(zhí)行
的帮辟,他們在使用 ptmalloc 也遇到了內(nèi)存暴增的相關(guān)問題,于是他們實現(xiàn)了 TCMalloc 來代
替 ptmalloc玩焰,TCMalloc 具有內(nèi)存池的優(yōu)點由驹,又有垃圾回收的機(jī)制,并最大限度優(yōu)化了鎖
的爭用昔园,并且空間利用率也高于 ptmalloc蔓榄。Ptmalloc 假設(shè)了線程 A 釋放的內(nèi)存塊能在線
程 B 中得到重用,但 B 不一定會分配和 A 線程同樣大小的內(nèi)存塊默刚,于是就需要不斷地做
切割和合并甥郑,可能導(dǎo)致內(nèi)存碎片。
5. 盡量減少程序的線程數(shù)量和避免頻繁分配/釋放內(nèi)存荤西,Ptmalloc 在多線程競爭激烈的情況
下澜搅,首先查看線程私有變量是否存在分配區(qū),如果存在則嘗試加鎖邪锌,如果加鎖不成功會
嘗試其它分配區(qū)勉躺,如果所有的分配區(qū)的鎖都被占用著,就會增加一個非主分配區(qū)供當(dāng)前
線程使用秃流。由于在多個線程的私有變量中可能會保存同一個分配區(qū)赂蕴,所以當(dāng)線程較多時,
加鎖的代價就會上升舶胀,ptmalloc 分配和回收內(nèi)存都要對分配區(qū)加鎖概说,從而導(dǎo)致了多線程
競爭環(huán)境下 ptmalloc 的效率降低。
6. 防止內(nèi)存泄露嚣伐,ptmalloc 對內(nèi)存泄露是相當(dāng)敏感的糖赔,根據(jù)它的內(nèi)存收縮機(jī)制,如果與 top
chunk 相鄰的那個 chunk 沒有回收轩端,將導(dǎo)致 top chunk 一下很多的空閑內(nèi)存都無法返回給
操作系統(tǒng)放典。
7. 防止程序分配過多內(nèi)存,或是由于 Glibc 內(nèi)存暴增基茵,導(dǎo)致系統(tǒng)內(nèi)存耗盡奋构,程序因 OOM 被
系 統(tǒng) 殺 掉 。 預(yù) 估 程 序 可 以 使 用 的 最 大 物 理 內(nèi) 存 大 小 拱层, 配 置 系 統(tǒng) 的
/proc/sys/vm/overcommit_memory弥臼,/proc/sys/vm/overcommit_ratio,以及使用 ulimt –v
限制程序能使用虛擬內(nèi)存空間大小根灯,防止程序因 OOM 被殺掉径缅。
5掺栅、GLBIC 申請或者收縮(釋放)域值調(diào)整
1. M_MXFAST
M_MXFAST 用于設(shè)置 fast bins 中保存的 chunk 的最大大小,默認(rèn)值為 64B纳猪,fast bins 中
保存的 chunk 在一段時間內(nèi)不會被合并氧卧,分配小對象時可以首先查找 fast bins,如果 fast bins
找到了所需大小的 chunk氏堤,就直接返回該 chunk沙绝,大大提高小對象的分配速度,但這個值設(shè)
置得過大丽猬,會導(dǎo)致大量內(nèi)存碎片宿饱,并且會導(dǎo)致 ptmalloc 緩存了大量空閑內(nèi)存,去不能歸還給
操作系統(tǒng)脚祟,導(dǎo)致內(nèi)存暴增谬以。
2. M_TRIM_THRESHOLD
M_TRIM_THRESHOLD 用于設(shè)置 mmap 收縮閾值,默認(rèn)值為 128KB由桌。自動收縮只會在 free
時才發(fā)生为黎,如果當(dāng)前 free 的 chunk 大小加上前后能合并 chunk 的大小大于 64KB,并且 top
chunk 的大小達(dá)到 mmap 收縮閾值行您,對于主分配區(qū)铭乾,調(diào)用 malloc_trim()返回一部分內(nèi)存給操
作系統(tǒng),對于非主分配區(qū)娃循,調(diào)用 heap_trim()返回一部分內(nèi)存給操作系統(tǒng)炕檩,在發(fā)生內(nèi)存收縮
時,還是從新設(shè)置 mmap 分配閾值和 mmap 收縮閾值捌斧。
3. M_MMAP_THRESHOLD
M_MMAP_THRESHOLD 用于設(shè)置 mmap 分配閾值笛质,默認(rèn)值為 128KB,ptmalloc 默認(rèn)開啟
動態(tài)調(diào)整 mmap 分配閾值和 mmap 收縮閾值捞蚂。
4. M_MMAP_MAX
M_MMAP_MAX 用于設(shè)置進(jìn)程中用 mmap 分配的內(nèi)存塊的最大限制妇押,默認(rèn)值為 64K,因
為有些系統(tǒng)用 mmap 分配的內(nèi)存塊太多會導(dǎo)致系統(tǒng)的性能下降姓迅。
代碼設(shè)置:
include <malloc.h>
mallopt(M_TRIM_THRESHOLD, 32 * 1024);
mallopt(M_MMAP_THRESHOLD, 64 * 1024);