linux-04-內(nèi)存管理函數(shù)

今天:-malloc() free() sbrk() brk() mmap() munmap()

文件讀寫函數(shù)(UC版)

malloc() 和 free()

malloc()分配的是堆區(qū)的內(nèi)存 一次申請小塊內(nèi)存時,系統(tǒng)會映射33個內(nèi)存頁,如果申請大塊內(nèi)存(31個內(nèi)存頁以上),系統(tǒng)會映射比申請稍多一點的內(nèi)存頁數(shù)。

malloc申請內(nèi)存時,除了數(shù)據(jù)占用的空間外,還需要額外占用一些空間,用于存儲附加數(shù)據(jù)。malloc申請內(nèi)存時,會包括三部分:數(shù)據(jù)本身的空間,附加數(shù)據(jù)的空間,空的空間(預(yù)留空間)。附加數(shù)據(jù)存于 底層維護(hù)的雙向鏈表中。預(yù)留空間的大小不確定,可大可小。

int* pi = malloc(4);

free(pi);//free()釋放到哪里結(jié)束呢? 附加數(shù)據(jù)中有。

理論上因為malloc()會映射多個內(nèi)存頁,導(dǎo)致未分配的內(nèi)存只要在33頁之內(nèi)都能使用;但是為了便于內(nèi)存的管理(反復(fù)使用和控制),內(nèi)存還是要 先分配再使用。

free()一定會釋放被占用的虛擬內(nèi)存地址,但是不一定會解除內(nèi)存映射,對于malloc()來說,free()不會釋放最后的33個內(nèi)存頁映射。最后33個內(nèi)存頁的映射在進(jìn)程結(jié)束時才會釋放。free()在大多數(shù)情況下會清空內(nèi)存,但是不保證清()

free對于申請大塊內(nèi)存時會 全部解除映射。

經(jīng)驗:malloc()雖然地址不連續(xù),但是不影響內(nèi)存的使用;malloc()申請的內(nèi)存在使用時不要過界,否則會影響下一次的內(nèi)存分配和回收。

sbrk()和brk()

sbrk()和brk()是Unix的系統(tǒng)函數(shù),機(jī)制和malloc是完全不同的。借助系統(tǒng)維護(hù)的一個位置進(jìn)行內(nèi)存的分配和回收。

void* sbrk(int increment) 功能就是分配//回收內(nèi)存,大多數(shù)情況下用于分配內(nèi)存。

參數(shù)increment是分配/回收的增量,為正數(shù)分配,為負(fù)數(shù)時,回收,為0時候取當(dāng)前值。

返回值返回移動之前的位置,如果出錯返回(void*) -1.

sbrk()在分配內(nèi)存時非常方便,但回收內(nèi)存時需要計算字節(jié)數(shù),因此比較麻煩,不便于管理。brk()則相反。

一般情況下都是使用sbrk()分配內(nèi)存,使用brk()釋放內(nèi)存(雖然這兩個函數(shù)都可以分配和回收)。

sbrk()和brk()都是以一個內(nèi)存頁作為映射的基本單位的,一旦釋放就會同時解除內(nèi)存映射。

int brk(void* position) 功能就是分配/回收內(nèi)存,一般用于回收內(nèi)存

參數(shù)position就是新位置,無論原來的位置在哪里。返回:成功返回0,失敗返回 -1。

brk() 和sbrk() 不會清除回收內(nèi)存的數(shù)據(jù),數(shù)據(jù)會在下次使用時被覆蓋。

memset()可以設(shè)置內(nèi)存的內(nèi)容,一般用于清內(nèi)存;

memcpy()可以復(fù)制內(nèi)存的內(nèi)容,一般用內(nèi)存復(fù)制。

mmap() 和munmap()

用戶層能使用的功能最強(qiáng)大的函數(shù),可以設(shè)置一些內(nèi)存相關(guān)的數(shù)據(jù)。mmap()實現(xiàn)內(nèi)存映射,包括:映射物理內(nèi)存和硬盤文件

各種權(quán)限和多個選項用位或 | 連接。

RWX

R-- 100

-W- 010

--X 001

讀+寫

100 | 010

void* mmap(void* addr,size_t length, int prot, int flats, int fd, off_t offset)

功能是內(nèi)存映射,比sbrk()功能強(qiáng)大的多,失敗返回-1

參數(shù):addr指定映射的首地址,為0就是交給內(nèi)核選擇。

size 就是映射內(nèi)存的大小

prot 就是內(nèi)存的權(quán)限 一般是PROT——READ|PROT——WRITE

flats 就是映射的標(biāo)識 主要包括:

MAP_SHARD MAP_PRIVATE 2選1,

MAP_SHARED 代表這塊內(nèi)存其他進(jìn)程可以共享,但只對映射文件有效

MAP_PRIVATE就是其他進(jìn)程不能共享,只能本進(jìn)程使用。

MAP——ANONYMOUS代表映射 物理內(nèi)存,不寫就映射硬盤文件(默認(rèn)映射)。

fd 是文件描述符,映射文件時有效,映射物理內(nèi)存為0.

offset 是文件偏移量,選擇映射文件的位置,映射物理內(nèi)存 為0;

返回:成功返回映射的首地址,失敗返回MAP——FAILED

用戶空間的程序不能進(jìn)入內(nèi)核空間,但很多功能需要內(nèi)核實現(xiàn),因此內(nèi)核空間 提供了一系列的函數(shù), 允許用戶空間調(diào)用,從而進(jìn)入內(nèi)核空間。這一系列的函數(shù)通稱為 系統(tǒng)調(diào)用(system call)。比如:標(biāo)C的malloc() 不能進(jìn)入Unix內(nèi)核,但內(nèi)存分配必須依賴內(nèi)核,內(nèi)核提供了系統(tǒng)調(diào)用sbrk()和mmap(),幫助malloc()進(jìn)入內(nèi)核完成內(nèi)存的分配。

系統(tǒng)調(diào)用的使用方式和標(biāo)C函數(shù)沒有任何區(qū)別,因此無需過多關(guān)注。

eg:

int* pi =mmap(NULL,//首地址內(nèi)核選擇

6? ? ? ? ? ? ? 4,//分配4字節(jié),映射還是按一頁算

7? ? ? ? ? ? ? PROT_READ | PROT_WRITE,//權(quán)限

8? ? ? ? ? ? ? MAP_PRIVATE | MAP_ANONYMOUS,//映射物理內(nèi)存用? ? PRIVATE,ANNONYMOU? ? S代表映射物理內(nèi)存

9? ? ? ? ? ? ? 0,0);//文件描述符映射物理內(nèi)存給()

10? if(pi == MAP_FAILED)

11? {

12? ? perror("MMAP");

13? ? return -1;

14? }

15? *pi = 100;

16 printf("%d\n",*pi);

17 munmap(pi,4);

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容