內存分配器一

glibc內存管理學習
http://www.cnblogs.com/tianchi/archive/2012/08/02/2620634.html
x86平臺Linux進程內存佈局:
text:ELF格式程序代碼
data:程序運行時就能確定的數據,可讀可寫
bss:沒有初始化的全局變量和靜態表裏
heap
stack:由編譯器自動分配釋放,存放函數參數、局部變量等
Mmap:映射區域
實現一個malloc
http://blog.jobbole.com/75656/
分頁與地址
現代操作系統中,不論是虛擬內存還是物理內存,都不是以字節爲單位進行管理的,而是以頁(page)爲單位。一般內存頁的大小爲4k(4096Byte),需要12位的地址,內存地址是以頁號加一個12位的偏移組成。

實現malloc
void * malloc(size_t size)
函數的主要功能是分配大小至少爲size參數所指定的字節數並返回一個一個指針指向該內存地址的首地址
實現參照http://www.inf.udec.cl/~leo/Malloc_tutorial.pdf
首先簡單實現函數:
IMalloc.h:

#ifndef IMALLOC_H
#define IMALLOC_H
#include<unistd.h>
#include<sys/types.h>
void *Imalloc(size_t size);
#endif`

IMalloc.c:

#include"IMalloc.h"
void *Imalloc(size_t size)
{
    void *p;
    p=sbrk(0);
    if(sbrk(size)==(void*)-1)       
        return NULL;
    return p;   
}

其中函數
void *sbrk(intptr_t increment);
是用來獲取Heap區域的break點,由於受物理存儲量的限制,整個堆虛擬內存空間不可能全部映射到實際物理內存地址中。從堆起始地址到break之間的地址空間爲映射好的,可以供進程訪問;而從break往上,是未映射的地址空間,如果訪問這段空間則程序會報錯。
main.c:

#include"IMalloc.h"
int main(void)
{
    int *p=(int*)Imalloc(sizeof(int)*2);
    int *pp=(int*)Imalloc(sizeof(int)*1);
    void *cur=sbrk(0);
    p[0]=1;
    p[1]=2;
    p[2]=3;
    pp[0]=4;
    pp[1]=5;
    pp[2]=5;
    pp[1028]=10;
    return 0;
}

編譯鏈接可以在gdb中調試:
gcc -g main.c IMalloc.c -o main
(gdb) main
(gdb) start

然後執行到
(gdb) n
10 p[2]=3;

可以查看內存如下,p[0]和p[1]中的值爲1和2
(gdb) x/8a p
0x804b000: 0x1 0x2 0x0 0x0
0x804b010: 0x0 0x0 0x0 0x0

越界操作,修改了p[2]地址中的值
(gdb) n
11 pp[0]=4;
(gdb) x/8a p
0x804b000: 0x1 0x2 0x3 0x0
0x804b010: 0x0 0x0 0x0 0x0

然後執行將值修改回來
(gdb) n
12 pp[1]=5;
(gdb) x/8a p
0x804b000: 0x1 0x2 0x4 0x0
0x804b010: 0x0 0x0 0x0 0x

當執行到pp[1028]=10這段代碼之前,可以修改當前heap的break後面內存的值。
(gdb) n
14 pp[1028]=10;
(gdb) x/8a p
0x804b000: 0x1 0x2 0x4 0x5
0x804b010: 0x5 0x0 0x0 0x0

當前break指向的地址爲如下所示,在pp[2]之前
(gdb) display cur
1: cur = (void *) 0x804b00c

但是當我們訪問超出一頁內存(4k)時,會報錯
Program received signal SIGSEGV, Segmentation fault.
0x080484a7 in main () at main.c:14
14 pp[1028]=10;

說明了一點heap上面映射的區域是一頁一頁映射的,當訪問當前break之後的一頁的內存時會出錯。
當修改代碼爲如下時,則可以正常執行。

int *pp=(int*)Imalloc(sizeof(int)*1028);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章