歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux Slab分配器(六)--創建slab和銷毀slab

Linux Slab分配器(六)--創建slab和銷毀slab

日期:2017/3/1 10:19:10   编辑:Linux編程

在滿足以下兩個條件時,slab分配器將為高速緩存創建新的slab

1.請求分配對象,但本地高速緩存沒有空閒對象可以分配,需要填充

2.kmem_list3維護的鏈表中沒有slab或者所有的slab都處於FULL鏈表中

這時,調用cache_grow()創建slab增大緩存容量

相關閱讀:

Linux Slab分配器(一)--概述 http://www.linuxidc.com/Linux/2012-06/62965.htm
Linux Slab分配器(二)--初始化 http://www.linuxidc.com/Linux/2012-06/62966.htm
Linux Slab分配器(三)--創建緩存 http://www.linuxidc.com/Linux/2012-06/63109.htm
Linux Slab分配器(四)--分配對象 http://www.linuxidc.com/Linux/2012-06/63138.htm

下圖給出了cache_grow()的代碼流程

  1. static int cache_grow(struct kmem_cache *cachep,
  2. gfp_t flags, int nodeid, void *objp)
  3. {
  4. struct slab *slabp;
  5. size_t offset;
  6. gfp_t local_flags;
  7. struct kmem_list3 *l3;
  8. /*
  9. * Be lazy and only check for valid flags here, keeping it out of the
  10. * critical path in kmem_cache_alloc().
  11. */
  12. BUG_ON(flags & GFP_SLAB_BUG_MASK);
  13. local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK);
  14. /* Take the l3 list lock to change the colour_next on this node */
  15. check_irq_off();
  16. l3 = cachep->nodelists[nodeid];
  17. spin_lock(&l3->list_lock);
  18. /* Get colour for the slab, and cal the next value. */
  19. /*確定待創建的slab的顏色編號*/
  20. offset = l3->colour_next;
  21. /*更新下一個slab的顏色編號*/
  22. l3->colour_next++;
  23. /*顏色編號必須小於顏色數*/
  24. if (l3->colour_next >= cachep->colour)
  25. l3->colour_next = 0;
  26. spin_unlock(&l3->list_lock);
  27. /*確定待創建的slab的顏色*/
  28. offset *= cachep->colour_off;
  29. if (local_flags & __GFP_WAIT)
  30. local_irq_enable();
  31. /*
  32. * The test for missing atomic flag is performed here, rather than
  33. * the more obvious place, simply to reduce the critical path length
  34. * in kmem_cache_alloc(). If a caller is seriously mis-behaving they
  35. * will eventually be caught here (where it matters).
  36. */
  37. kmem_flagcheck(cachep, flags);
  38. /*
  39. * Get mem for the objs. Attempt to allocate a physical page from
  40. * 'nodeid'.
  41. */
  42. if (!objp)
  43. /*從伙伴系統分配頁框,這是slab分配器與伙伴系統的接口*/
  44. objp = kmem_getpages(cachep, local_flags, nodeid);
  45. if (!objp)
  46. goto failed;
  47. /* Get slab management. */
  48. /*分配slab管理區*/
  49. slabp = alloc_slabmgmt(cachep, objp, offset,
  50. local_flags & ~GFP_CONSTRAINT_MASK, nodeid);
  51. if (!slabp)
  52. goto opps1;
  53. /*建立頁面到slab和cache的映射,以便於根據obj迅速定位slab描述符和cache描述符*/
  54. slab_map_pages(cachep, slabp, objp);
  55. /*初始化對象*/
  56. cache_init_objs(cachep, slabp);
  57. if (local_flags & __GFP_WAIT)
  58. local_irq_disable();
  59. check_irq_off();
  60. spin_lock(&l3->list_lock);
  61. /* Make slab active. */
  62. /*將新創建的slab添加到free鏈表*/
  63. list_add_tail(&slabp->list, &(l3->slabs_free));
  64. STATS_INC_GROWN(cachep);
  65. l3->free_objects += cachep->num;
  66. spin_unlock(&l3->list_lock);
  67. return 1;
  68. opps1:
  69. kmem_freepages(cachep, objp);
  70. failed:
  71. if (local_flags & __GFP_WAIT)
  72. local_irq_disable();
  73. return 0;
  74. }
Copyright © Linux教程網 All Rights Reserved