今天:-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);