palloc.c

來源:互聯網
上載者:User

這個源檔案主要講的是頁分配的過程。
enum palloc_flags
  {
    PAL_ASSERT = 001,           /* Panic on failure. */
    PAL_ZERO = 002,             /* Zero page contents. */
    PAL_USER = 004              /* User page. */
  };
頁分配時可以有三種狀態,
PAL_ASSERT:如果頁不能被分配,則kernel panics
PAL_ZERO:分配頁時清零。
PAL_USER:從user pool中分配頁。
前面兩種是從kernel pool中分配頁。
我們把記憶體分成兩種類型。一種是user pool,一種是kernel pool。
struct pool
  {
    struct lock lock;                   /* Mutual exclusion. */
    struct bitmap *used_map;            /* Bitmap of free pages. */
    uint8_t *base;                      /* Base of pool. */
  };
這裡我們用bitmap來表明閒置頁。這個和資料庫的位元影像索引等都是差不多的。
lock是為了在尋找bitmap的時候只能是原子的。
void
palloc_init (size_t user_page_limit)
{
  /* Free memory starts at 1 MB and runs to the end of RAM. */
  uint8_t *free_start = ptov (1024 * 1024);  //起始從1MB開始
  uint8_t *free_end = ptov (init_ram_pages * PGSIZE); //結束是ram的頁數*4KB
  size_t free_pages = (free_end - free_start) / PGSIZE; //一共有幾頁空的
  size_t user_pages = free_pages / 2;   //如果一半空間不到user_page_limit,則不變,如果大於user_page_limit,則縮小為這個值。
  size_t kernel_pages;   //
  if (user_pages > user_page_limit)
    user_pages = user_page_limit;
  kernel_pages = free_pages - user_pages;  //其餘的閒置頁賦給核心。

  /* Give half of memory to kernel, half to user. */
  init_pool (&kernel_pool, free_start, kernel_pages, "kernel pool");
  init_pool (&user_pool, free_start + kernel_pages * PGSIZE,
             user_pages, "user pool");
}
這個是記憶體的分池,user_page_limit參數是為了限制使用者池的大小一定要在這個大小以內。

void *
palloc_get_multiple (enum palloc_flags flags, size_t page_cnt)
{
  struct pool *pool = flags & PAL_USER ? &user_pool : &kernel_pool;    //選擇pool的類型。
  void *pages;
  size_t page_idx;         

  if (page_cnt == 0)        //需求的頁數量為0
    return NULL;

  lock_acquire (&pool->lock);
  page_idx = bitmap_scan_and_flip (pool->used_map, 0, page_cnt, false); //尋找第一個連續page_cnt的空頁的頁位置,即是第幾個頁。
  lock_release (&pool->lock);

  if (page_idx != BITMAP_ERROR)
    pages = pool->base + PGSIZE * page_idx; //找到頁具體位置
  else
    pages = NULL;

  if (pages != NULL)
    {
      if (flags & PAL_ZERO)
        memset (pages, 0, PGSIZE * page_cnt); //如果PAL_ZERO,則分配是還要清零。
    }
  else
    {
      if (flags & PAL_ASSERT)
        PANIC ("palloc_get: out of pages");
    }

  return pages;
}
//-----------------------------------------------------------------------------------------------------
static bool
page_from_pool (const struct pool *pool, void *page)
{
  size_t page_no = pg_no (page);
  size_t start_page = pg_no (pool->base);
  size_t end_page = start_page + bitmap_size (pool->used_map);
  return page_no >= start_page && page_no < end_page;
}
pg_no是把虛擬位址轉為他所在的頁號,因此如果page_no在start_page和end_page之間,則說明這個頁已經分配了。

當free-page時要把這些頁設為0xcc。
//-------------------------------------------------------------------------------------------------------
static void
init_pool (struct pool *p, void *base, size_t page_cnt, const char *name)
//池中除了要放空閑頁,還要放bitmap,這個是用來記錄的。因此bm_pages就是bitmap所佔的頁數。
p池為從base開始page_cnt頁數的一個池,。
{
  size_t bm_pages = DIV_ROUND_UP (bitmap_buf_size (page_cnt), PGSIZE);
  if (bm_pages > page_cnt)  //如果分配給池的大小還不能裝的下bitmap。則不夠。
    PANIC ("Not enough memory in %s for bitmap.", name);
  page_cnt -= bm_pages;   //page_cnt-bm_pages為真正閒置頁數。

  printf ("%zu pages available in %s./n", page_cnt, name);

  /* Initialize the pool. */
  lock_init (&p->lock);
  p->used_map = bitmap_create_in_buf (page_cnt, base, bm_pages * PGSIZE); 
  p->base = base + bm_pages * PGSIZE;   //池的基地址是原來的base+bitmap_page*PGSIZE;這才是真正的基地址。池的base是指除了bitmap空間的基地址。
}
                                                                                             高
|                                                                                       ||          <-----整體是一個pool
|--------------------------------------------------------------------- ||          <-----page_get_multiple()後返回的指標                   
|                         分配的空間                                               ||   地址
|                                                                                       ||
|----------------------------------------------------------------------||         <-----base (一直不會變)
|DIV_ROUND_UP (bitmap_buf_size (page_cnt), PGSIZE);||         <-----page_cnt要用的空間
|----------------------------------------------------------------------||  |低

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.