記憶體管理函式

2021-09-19 03:14:36 字數 3161 閱讀 7804

一、基本用法

#include int brk(void *addr);

void *sbrk(intptr_t increment); //返回空間位址

brk是系統呼叫,通過傳遞的addr來重新設定program break,成功返回0,否則返回-1。

sbrk不是系統呼叫,是c庫函式,用來增加heap,增加的大小通過引數increment來決定。increment可以是正負、負數、零。

brk和sbrk會改變program break的位置,program break被定義為程式資料段的結束位置。這裡的程式資料段包含data segment、bss segment和heap,所以program break就是指heap的結束位址。

#include // 將乙個檔案或者其它物件對映進記憶體

void *mmap(void *start, size_t length, int port, int flags, int fd, off_t offset);

// 成功返回被對映區的指標,失敗返回map_failed(其值為(void *)-1)。

int munmap(void *start, size_t length);

// 成功返回0,失敗返回-1。

#include void *alloca(size_t);

#include void* malloc(unsigned size);

void* calloc(size_t numelements, size_t sizeofelement);

void* realloc(void* ptr, unsigned newsize);

(1)alloca是向棧申請記憶體,因此無需手動釋放。

(2)malloc向堆中申請記憶體,不能初始化所分配的記憶體,因此需要呼叫memset來初始化這部分的記憶體空間。

(3)calloc與malloc類似,會將所分配的記憶體空間中的每一位都初始化為零(空指標)。

(4)realloc給乙個已經分配了位址的指標重新分配空間,引數ptr為原有的空間位址,newsize是重新申請的位址長度。

realloc可能會導致資料移動。realloc可以對給定的指標所指的空間進行擴大或者縮小,無論是擴張或是縮小,原有記憶體的中內容將保持不變。對於縮小,則被縮小的那一部分的內容會丟失。對於擴大,realloc()試圖直接從堆上現存的資料後面的那些位元組中獲得附加的位元組,如果滿足則直接返回,如果不滿足,就使用堆上第乙個有足夠大小的自由塊,將現存的資料拷貝至新的位置,老的資料塊放回到堆中。

如果 ptr = null,那麼相當於呼叫 malloc(size);如果 size = 0,那麼相當於呼叫 free(ptr)

如果 ptr 不為 null,那麼他肯定是由之前的記憶體分配函式返回的,例如 malloc()、calloc()或realloc(),如果 ptr 所指的記憶體塊被移動,那麼會呼叫 free(ptr)

二、程序的記憶體使用

1、當乙個程序發生缺頁中斷的時候,程序會陷入核心態,執行以下操作:

(1)檢查要訪問的虛擬位址是否合法

(2)查詢/分配乙個物理頁

(3)填充物理頁內容(讀取磁碟、或者直接置0、或者啥也不幹)

(4)建立對映關係(虛位址到實體地址)

重新執行發生缺頁中斷的那條命令

如果第3步需要讀取磁碟,那麼這次缺頁中斷就是majflt,否則就是minflt。

// 檢視程序發生缺頁中斷的次數

ps -o majflt,minflt -c program_name

其中majflt代表major fault,中文名叫大錯誤。minflt代表minor fault,中文名叫小錯誤。

這兩個數值表示乙個程序自啟動以來所發生的缺頁中斷的次數,是乙個累加值。

2、從作業系統角度來看,程序分配記憶體有兩種方式,分別由兩個系統呼叫完成:brk和mmap。

(1)brk是將資料段(.data)的最高位址指標_edata往高位址推

(2)mmap是在程序的虛擬位址空間中(堆和棧中間,稱為檔案對映區域的地方)找一塊空閒的虛擬記憶體。

這兩種方式分配的都是虛擬記憶體,沒有分配物理記憶體。在第一次訪問已經分配的虛擬位址空間的時候,發生缺頁中斷,

作業系統負責分配物理記憶體,然後建立虛擬記憶體和物理記憶體之間的對映關係。

3、標準c庫中,提供了malloc/free函式分配釋放記憶體,這兩個函式底層是由brk/mmap、munmap這些系統呼叫實現的。

malloc小於128k的記憶體,使用brk分配記憶體,將_edata往高位址推(只分配虛擬位址,不對應物理記憶體)。

malloc大於128k的記憶體(可由m_mmap_threshold選項調節)使用mmap系統呼叫,從堆和棧的中間分配一塊虛擬記憶體。

第一次讀/寫資料時,引起核心缺頁中斷,核心才分配對應的物理記憶體,然後與虛擬位址空間建立對映關係。

如果malloc分配了a這塊記憶體後,從來不訪問它,那麼a對應的物理頁是不會被分配的。

[2]程序呼叫b=malloc(40k),則將_edata指標再往高位址推40k。

[3]程序呼叫c=malloc(100k),則將_edata指標再往高位址推100k。

[4]程序呼叫free(b),此時b的虛擬記憶體和物理記憶體都沒有釋放,因為只有乙個_edata指標,如果往回推,那麼c這塊記憶體怎麼辦。當然,b這塊記憶體是可以重用的,如果這個時候再來乙個40k的請求,那麼malloc很可能就把b這塊記憶體返回出去。

[5]程序呼叫free(c),此時b和c連線起來,變成一塊140k的空閒記憶體。

預設情況下,當最高位址的空閒記憶體超過128k(可由m_trim_threshold選項調節)時,執行記憶體緊縮操作(trim)。在步驟[5]執行free操作時,發現最高位址空閒記憶體超過128k,於是記憶體緊縮。

[6]程序呼叫d=malloc(200k),malloc函式呼叫mmap系統呼叫,在檔案對映區分配200k虛擬記憶體。

[7]程序呼叫free(d),d對應的虛擬記憶體和物理記憶體一起釋放。

C記憶體管理函式

在c裡,記憶體管理是通過專門的函式來實現。另外,為了相容各種程式語言,作業系統提供的介面通常是 c 語言寫成的函式宣告 windows 本身也由c和組合語言寫成 1分配記憶體 malloc函式 需要包含標頭檔案 include 或 include 函式宣告 函式原型 void malloc int ...

記憶體管理相關函式

記憶體分配及釋放相關函式 void calloc int num,int size 在記憶體中動態地分配 num 個長度為 size 的連續空間,並將每乙個位元組 共num size 個 都初始化為 0。void malloc int num 在堆區分配一塊指定大小的記憶體空間,用來存放資料。這塊記...

C 記憶體管理函式

建立乙個file 指標,連線到檔案上函式原型 file fopen const char path const char mode 引數 filename 指定絕對路徑或者相對路徑的檔名mode 分別指定 r 當檔案存在返回有效的檔案指標,當檔案不存在返回空指標 w 如果檔案不存在,建立檔案,如果檔...