首頁 > 軟體

Linux核心的冷熱快取

2020-06-16 16:39:59

快取為什麼會有冷熱?

究其原因,是因為對於記憶體的存取,可能是CPU發起的,也可以是DMA裝置發起的。

如果是CPU發起的,在CPU的硬體快取中,就會儲存相應的頁內容。如果這個頁本來沒有存在於硬體快取中,那麼它的到來,勢必會將原本為其他的頁快取的內容擠出硬體快取。

但是,如果對於記憶體的存取是由DMA裝置發起的,那麼該頁不會被CPU存取,就不需要在CPU的硬體快取中進行快取,也不會對已經快取在硬體快取中的頁內容造成傷害。

在Linux作業系統中,每個記憶體區域(Zone)都分配了hot cache和cold cache,hot cache用來快取那些很可能被CPU的硬體快取收納了的頁。

hot/cold cache只處理單頁分配的情況。

    1: /*
   2:  * Really, prep_compound_page() should be called from __rmqueue_bulk().  But
   3:  * we cheat by calling it from here, in the order > 0 path.  Saves a branch
   4:  * or two.
   5:  */
   6: static inline
   7: struct page *buffered_rmqueue(struct zone *preferred_zone,
   8:             struct zone *zone, int order, gfp_t gfp_flags,
   9:             int migratetype)
  10: {
  11:     unsigned long flags;
  12:     struct page *page;
  13:     int cold = !!(gfp_flags & __GFP_COLD);
  14:  
  15: again:
  16:     if (likely(order == 0)) {
  17:         struct per_cpu_pages *pcp;
  18:         struct list_head *list;
  19:  
  20:         local_irq_save(flags);
  21:         pcp = &this_cpu_ptr(zone->pageset)->pcp;
  22:         list = &pcp->lists[migratetype];
  23:         if (list_empty(list)) {
  24:             pcp->count += rmqueue_bulk(zone, 0,
  25:                     pcp->batch, list,
  26:                     migratetype, cold);
  27:             if (unlikely(list_empty(list)))
  28:                 goto failed;
  29:         }
  30:  
  31:         if (cold)
  32:             page = list_entry(list->prev, struct page, lru);
  33:         else
  34:             page = list_entry(list->next, struct page, lru);
  35:  
  36:         list_del(&page->lru);
  37:         pcp->count--;
  38:     } else {
  39:         if (unlikely(gfp_flags & __GFP_NOFAIL)) {
  40:             /*
  41:              * __GFP_NOFAIL is not to be used in new code.
  42:              *
  43:              * All __GFP_NOFAIL callers should be fixed so that they
  44:              * properly detect and handle allocation failures.
  45:              *
  46:              * We most definitely don't want callers attempting to
  47:              * allocate greater than order-1 page units with
  48:              * __GFP_NOFAIL.
  49:              */
  50:             WARN_ON_ONCE(order > 1);
  51:         }
  52:         spin_lock_irqsave(&zone->lock, flags);
  53:         page = __rmqueue(zone, order, migratetype);
  54:         spin_unlock(&zone->lock);
  55:         if (!page)
  56:             goto failed;
  57:         __mod_zone_page_state(zone, NR_FREE_PAGES, -(1 << order));
  58:     }
  59:  
  60:     __count_zone_vm_events(PGALLOC, zone, 1 << order);
  61:     zone_statistics(preferred_zone, zone, gfp_flags);
  62:     local_irq_restore(flags);
  63:  
  64:     VM_BUG_ON(bad_range(zone, page));
  65:     if (prep_new_page(page, order, gfp_flags))
  66:         goto again;
  67:     return page;
  68:  
  69: failed:
  70:     local_irq_restore(flags);
  71:     return NULL;
  72: }

buffered_rmqueue用於從冷熱分配器中分配單頁的快取頁。

如果gfp_flags中指定的__GFP_COLD,則從冷快取中分配一頁,否則,從熱快取中分配。


IT145.com E-mail:sddin#qq.com