實現記憶體的整頁分配

2021-10-05 11:25:10 字數 3593 閱讀 8058

1、點陣圖和記憶體池:

位圖:點陣圖中的一位表示物理記憶體中的一頁是否被分配,api見blog:點陣圖api

位圖結構:

struct bitmap ;
struct pool ;
struct virtual_addr ;
3、初始化點陣圖和記憶體池:

uint32_t page_table_size = pg_size * 256;	  // 頁表大小= 1頁的頁目錄表+第0和第768個頁目錄項指向同乙個頁表+

// 第769~1022個頁目錄項共指向254個頁表,共256個頁框

uint32_t used_mem = page_table_size + 0x100000; // 0x100000為低端1m記憶體

uint32_t free_mem = all_mem - used_mem;

uint16_t all_free_pages = free_mem / pg_size; // 1頁為4k,不管總記憶體是不是4k的倍數,

uint16_t kernel_free_pages = all_free_pages / 2;

uint16_t user_free_pages = all_free_pages - kernel_free_pages;

uint32_t kbm_length = kernel_free_pages / 8; // kernel bitmap的長度,點陣圖中的一位表示一頁,以位元組為單位

uint32_t ubm_length = user_free_pages / 8; // user bitmap的長度.

uint32_t kp_start = used_mem; // kernel pool start,核心記憶體池的起始位址

uint32_t up_start = kp_start + kernel_free_pages * pg_size; // user pool start,使用者記憶體池的起始位址

kernel_pool.phy_addr_start = kp_start;

user_pool.phy_addr_start = up_start;

kernel_pool.pool_size = kernel_free_pages * pg_size;

user_pool.pool_size = user_free_pages * pg_size;

kernel_pool.pool_bitmap.btmp_bytes_len = kbm_length;

user_pool.pool_bitmap.btmp_bytes_len = ubm_length;

// 核心位圖位址為0xc009a000

kernel_pool.pool_bitmap.bits = (void*)mem_bitmap_base;

/* 使用者記憶體池的點陣圖緊跟在核心記憶體池位圖之後 */

user_pool.pool_bitmap.bits = (void*)(mem_bitmap_base + kbm_length);

/* 將位圖置0*/

bitmap_init(&kernel_pool.pool_bitmap);

bitmap_init(&user_pool.pool_bitmap);

/* 下面初始化核心虛擬位址的點陣圖,按實際物理記憶體大小生成陣列。*/

kernel_vaddr.vaddr_bitmap.btmp_bytes_len = kbm_length; // 用於維護核心堆的虛擬位址,所以要和核心記憶體池大小一致

/* 點陣圖的陣列指向一塊未使用的記憶體,目前定位在核心記憶體池和使用者記憶體池之外*/

kernel_vaddr.vaddr_bitmap.bits = (void*)(mem_bitmap_base + kbm_length + ubm_length);

kernel_vaddr.vaddr_start = k_heap_start;

bitmap_init(&kernel_vaddr.vaddr_bitmap);

實現邏輯:

(1)先在核心虛擬記憶體池中尋找空閒頁

(2)在物理記憶體池中尋找空閒頁

(2)編輯頁表,在虛擬記憶體和物理記憶體間建立對映

malloc_page ->

1、vaddr_get申請虛擬頁

2、palloc申請物理頁

3、page_table_add建立對映

malloc_page:

void* malloc_page(enum pool_flags pf, uint32_t pg_cnt) }

uint32_t vaddr = (uint32_t)vaddr_start, cnt = pg_cnt;

struct pool* mem_pool = pf & pf_kernel ? &kernel_pool : &user_pool;

/* 因為虛擬位址是連續的,但實體地址可以是不連續的,所以逐個做對映*/

while (cnt-- > 0)

page_table_add((void*)vaddr, page_phyaddr); // 在頁表中做對映

vaddr += pg_size; // 下乙個虛擬頁

}

static void* vaddr_get(enum pool_flags pf, uint32_t pg_cnt) 

while(cnt < pg_cnt)

vaddr_start = kernel_vaddr.vaddr_start + bit_idx_start * pg_size;

} else

return (void*)vaddr_start;

}

二、palloc:在m_pool指向的記憶體池中分配乙個物理頁

static void* palloc(struct pool* m_pool) 

bitmap_set(&m_pool->pool_bitmap, bit_idx, 1); // 將此位bit_idx置1

uint32_t page_phyaddr = ((bit_idx * pg_size) + m_pool->phy_addr_start);

return (void*)page_phyaddr;

}

static void page_table_add(void* _vaddr, void* _page_phyaddr) else 

} else

}

如果沒有pde,則需要palloc乙個物理頁作為頁表項,並將其實體地址填入pde中

(1)獲取pde指標的方法:前20位填充1,後12位填充pde的索引

uint32_t* pde_ptr(uint32_t vaddr)
(2)獲取pte指標的方法:前10位填充1,中間十位填充pde索引,最後12位填充pte索引

uint32_t* pte_ptr(uint32_t vaddr)

實現動態分配記憶體

有些時候我們需要在記憶體主動申請記憶體來儲存我們的資料,實現動態分配記憶體的效果,標頭檔案 include 宣告了個關於記憶體動態分配的函式 malloc 函式 函式原型 void malloc usigned int size 作用 在記憶體的動態儲存區 堆區 中分配乙個長度為size的連續空間。...

記憶體的分配

malloc 動態從記憶體中申請乙個空間 如果申請成功,將返回這個空間的首位址 通過乙個指標接受這個空間的首位址 int p p malloc sizeof int p 234 free p 釋放這個動態申請的空間 1.結構體的定義 struct 結構體名 struct npc 2.建立結構體變數 ...

記憶體的分配

需要使用 include include include 呼叫malloc函式所需的標頭檔案 intmain printf you number is n for i 0 i 1 不同機器對於各型別大小定義不同,因此最好使用sizeof 函式求型別大小 free 釋放引數指向的記憶體空間 函式原型 ...