歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux內存管理之slab機制(釋放對象)

Linux內存管理之slab機制(釋放對象)

日期:2017/2/28 15:59:54   编辑:Linux教程
Linux內核中將對象釋放到slab中上層所用函數為kfree()或kmem_cache_free()。兩個函數都會調用__cache_free()函數。

代碼執行流程:

1,當本地CPU cache中空閒對象數小於規定上限時,只需將對象放入本地CPU cache中;

2,當local cache中對象過多(大於等於規定上限),需要釋放一批對象到slab三鏈中。由函數cache_flusharray()實現。

1)如果三鏈中存在共享本地cache,那麼首先選擇釋放到共享本地cache中,能釋放多少是多少;

2)如果沒有shared local cache,釋放對象到slab三鏈中,實現函數為free_block()。對於free_block()函數,當三鏈中的空閒對象數過多時,銷毀此cache。不然,添加此slab到空閒鏈表。因為在分配的時候我們看到將slab結構從cache鏈表中脫離了,在這裡,根據page描述符的lru找到slab並將它添加到三鏈的空閒鏈表中。

主實現

  1. /*
  2. * Release an obj back to its cache. If the obj has a constructed state, it must
  3. * be in this state _before_ it is released. Called with disabled ints.
  4. */
  5. static inline void __cache_free(struct kmem_cache *cachep, void *objp)
  6. {
  7. /* 獲得本CPU的local cache */
  8. struct array_cache *ac = cpu_cache_get(cachep);
  9. check_irq_off();
  10. kmemleak_free_recursive(objp, cachep->flags);
  11. objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
  12. kmemcheck_slab_free(cachep, objp, obj_size(cachep));
  13. /*
  14. * Skip calling cache_free_alien() when the platform is not numa.
  15. * This will avoid cache misses that happen while accessing slabp (which
  16. * is per page memory reference) to get nodeid. Instead use a global
  17. * variable to skip the call, which is mostly likely to be present in
  18. * the cache.
  19. *//* NUMA相關 */
  20. if (nr_online_nodes > 1 && cache_free_alien(cachep, objp))
  21. return;
  22. if (likely(ac->avail < ac->limit)) {
  23. /* local cache中的空閒對象數小於上限時
  24. ,只需將對象釋放回entry數組中 */
  25. STATS_INC_FREEHIT(cachep);
  26. ac->entry[ac->avail++] = objp;
  27. return;
  28. } else {
  29. /* 大於等於上限時, */
  30. STATS_INC_FREEMISS(cachep);
  31. /* local cache中對象過多,需要釋放一批對象到slab三鏈中。*/
  32. cache_flusharray(cachep, ac);
  33. ac->entry[ac->avail++] = objp;
  34. }
  35. }

釋放對象到三鏈中

  1. /*local cache中對象過多,需要釋放一批對象到slab三鏈中。*/
  2. static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac)
  3. {
  4. int batchcount;
  5. struct kmem_list3 *l3;
  6. int node = numa_node_id();
  7. /* 每次���放多少個對象 */
  8. batchcount = ac->batchcount;
  9. #if DEBUG
  10. BUG_ON(!batchcount || batchcount > ac->avail);
  11. #endif
  12. check_irq_off();
  13. /* 獲得此cache的slab三鏈 */
  14. l3 = cachep->nodelists[node];
  15. spin_lock(&l3->list_lock);
  16. if (l3->shared) {
  17. /* 如果存在shared local cache,將對象釋放到其中 */
  18. struct array_cache *shared_array = l3->shared;
  19. /* 計算shared local cache中還有多少空位 */
  20. int max = shared_array->limit - shared_array->avail;
  21. if (max) {
  22. /* 空位數小於要釋放的對象數時,釋放數等於空位數 */
  23. if (batchcount > max)
  24. batchcount = max;
  25. /* 釋放local cache前面的幾個對象到shared local cache中
  26. ,前面的是最早不用的 */
  27. memcpy(&(shared_array->entry[shared_array->avail]),
  28. ac->entry, sizeof(void *) * batchcount);
  29. /* 增加shared local cache可用對象數 */
  30. shared_array->avail += batchcount;
  31. goto free_done;
  32. }
  33. }
  34. /* 無shared local cache,釋放對象到slab三鏈中 */
  35. free_block(cachep, ac->entry, batchcount, node);
  36. free_done:
  37. #if STATS
  38. {
  39. int i = 0;
  40. struct list_head *p;
  41. p = l3->slabs_free.next;
  42. while (p != &(l3->slabs_free)) {
  43. struct slab *slabp;
  44. slabp = list_entry(p, struct slab, list);
  45. BUG_ON(slabp->inuse);
  46. i++;
  47. p = p->next;
  48. }
  49. STATS_SET_FREEABLE(cachep, i);
  50. }
  51. #endif
  52. spin_unlock(&l3->list_lock);
  53. /* 減少local cache可用對象數*/
  54. ac->avail -= batchcount;
  55. /* local cache前面有batchcount個空位,將後面的對象依次前移batchcount位 */
  56. memmove(ac->entry, &(ac->entry[batchcount]), sizeof(void *)*ac->avail);
  57. }
Copyright © Linux教程網 All Rights Reserved