歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux Slab分配器(三)--創建緩存

Linux Slab分配器(三)--創建緩存

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

創建新的緩存必須通過kmem_cache_create()函數來完成,原型如下

  1. struct kmem_cache *
  2. kmem_cache_create (const char *name, size_t size, size_t align,
  3. unsigned long flags, void (*ctor)(void *))
  • name:所創建的新緩存的名字
  • size :緩存所分配對象的大小
  • align:對象的對齊值
  • flags:創建用的標識
  • ctor:創建對象時的構造函數

相關閱讀:

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

kmem_cache_create()的實際工作就是為新的緩存申請緩存描述符,array_cache描述符和kmem_list3描述符,並根據接收的參數對這三個結構中的變量進行相應的初始化。新創建的緩存是空的,不包含slab。

  1. struct kmem_cache *
  2. kmem_cache_create (const char *name, size_t size, size_t align,
  3. unsigned long flags, void (*ctor)(void *))
  4. {
  5. size_t left_over, slab_size, ralign;
  6. struct kmem_cache *cachep = NULL, *pc;
  7. gfp_t gfp;
  8. /*
  9. * Sanity checks... these are all serious usage bugs.
  10. */
  11. /*做一些必要的檢查,以下情況都是不合法的:
  12. 1.緩存名為空
  13. 2.處於中斷環境中
  14. 3.緩存中的對象大小小於處理器的字長
  15. 4.緩存中的對象大小大於普通緩存的最大長度*/
  16. if (!name || in_interrupt() || (size < BYTES_PER_WORD) ||
  17. size > KMALLOC_MAX_SIZE) {
  18. printk(KERN_ERR "%s: Early error in slab %s\n", __func__,
  19. name);
  20. BUG();
  21. }
  22. /*
  23. * We use cache_chain_mutex to ensure a consistent view of
  24. * cpu_online_mask as well. Please see cpuup_callback
  25. */
  26. if (slab_is_available()) {
  27. get_online_cpus();
  28. mutex_lock(&cache_chain_mutex);
  29. }
  30. list_for_each_entry(pc, &cache_chain, next) {
  31. char tmp;
  32. int res;
  33. /*
  34. * This happens when the module gets unloaded and doesn't
  35. * destroy its slab cache and no-one else reuses the vmalloc
  36. * area of the module. Print a warning.
  37. */
  38. res = probe_kernel_address(pc->name, tmp);
  39. if (res) {
  40. printk(KERN_ERR
  41. "SLAB: cache with size %d has lost its name\n",
  42. pc->buffer_size);
  43. continue;
  44. }
  45. if (!strcmp(pc->name, name)) {
  46. printk(KERN_ERR
  47. "kmem_cache_create: duplicate cache %s\n", name);
  48. dump_stack();
  49. goto oops;
  50. }
  51. }
  52. #if DEBUG
  53. WARN_ON(strchr(name, ' ')); /* It confuses parsers */
  54. #if FORCED_DEBUG
  55. /*
  56. * Enable redzoning and last user accounting, except for caches with
  57. * large objects, if the increased size would increase the object size
  58. * above the next power of two: caches with object sizes just above a
  59. * power of two have a significant amount of internal fragmentation.
  60. */
  61. if (size < 4096 || fls(size - 1) == fls(size-1 + REDZONE_ALIGN +
  62. 2 * sizeof(unsigned long long)))
  63. flags |= SLAB_RED_ZONE | SLAB_STORE_USER;
  64. if (!(flags & SLAB_DESTROY_BY_RCU))
  65. flags |= SLAB_POISON;
  66. #endif
  67. if (flags & SLAB_DESTROY_BY_RCU)
  68. BUG_ON(flags & SLAB_POISON);
  69. #endif
  70. /*
  71. * Always checks flags, a caller might be expecting debug support which
  72. * isn't available.
  73. */
  74. BUG_ON(flags & ~CREATE_MASK);
  75. /*
  76. * Check that size is in terms of words. This is needed to avoid
  77. * unaligned accesses for some archs when redzoning is used, and makes
  78. * sure any on-slab bufctl's are also correctly aligned.
  79. */
  80. /*如果緩存對象大小沒有對齊到處理器字長,則對齊之*/
  81. if (size & (BYTES_PER_WORD - 1)) {
  82. size += (BYTES_PER_WORD - 1);
  83. size &= ~(BYTES_PER_WORD - 1);
  84. }
  85. /* calculate the final buffer alignment: */
  86. /* 1) arch recommendation: can be overridden for debug */
  87. /*要求按照體系結構對齊*/
  88. if (flags & SLAB_HWCACHE_ALIGN) {
  89. /*
  90. * Default alignment: as specified by the arch code. Except if
  91. * an object is really small, then squeeze multiple objects into
  92. * one cacheline.
  93. */
  94. ralign = cache_line_size();/*對齊值取L1緩存行的大小*/
  95. /*如果對象大小足夠小,則不斷壓縮對齊值以保證能將足夠多的對象裝入一個緩存行*/
  96. while (size <= ralign / 2)
  97. ralign /= 2;
  98. } else {
  99. ralign = BYTES_PER_WORD; /*對齊值取處理器字長*/
  100. }
  101. /*
  102. * Redzoning and user store require word alignment or possibly larger.
  103. * Note this will be overridden by architecture or caller mandated
  104. * alignment if either is greater than BYTES_PER_WORD.
  105. */
  106. /*如果開啟了DEBUG,則按需要進行相應的對齊*/
  107. if (flags & SLAB_STORE_USER)
  108. ralign = BYTES_PER_WORD;
  109. if (flags & SLAB_RED_ZONE) {
  110. ralign = REDZONE_ALIGN;
  111. /* If redzoning, ensure that the second redzone is suitably
  112. * aligned, by adjusting the object size accordingly. */
  113. size += REDZONE_ALIGN - 1;
  114. size &= ~(REDZONE_ALIGN - 1);
  115. }
  116. /* 2) arch mandated alignment */
  117. if (ralign < ARCH_SLAB_MINALIGN) {
  118. ralign = ARCH_SLAB_MINALIGN;
  119. }
  120. /* 3) caller mandated alignment */
  121. if (ralign < align) {
  122. ralign = align;
  123. }
  124. /* disable debug if necessary */
  125. if (ralign > __alignof__(unsigned long long))
  126. flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
  127. /*
  128. * 4) Store it.
  129. */
  130. align = ralign;
  131. if (slab_is_available())
  132. gfp = GFP_KERNEL;
  133. else
  134. gfp = GFP_NOWAIT;
  135. /* Get cache's description obj. */
  136. /*從cache_cache中分配一個高速緩存描述符*/
  137. cachep = kmem_cache_zalloc(&cache_cache, gfp);
  138. if (!cachep)
  139. goto oops;
  140. #if DEBUG
  141. cachep->obj_size = size;
  142. /*
  143. * Both debugging options require word-alignment which is calculated
  144. * into align above.
  145. */
  146. if (flags & SLAB_RED_ZONE) {
  147. /* add space for red zone words */
  148. cachep->obj_offset += sizeof(unsigned long long);
  149. size += 2 * sizeof(unsigned long long);
  150. }
  151. if (flags & SLAB_STORE_USER) {
  152. /* user store requires one word storage behind the end of
  153. * the real object. But if the second red zone needs to be
  154. * aligned to 64 bits, we must allow that much space.
  155. */
  156. if (flags & SLAB_RED_ZONE)
  157. size += REDZONE_ALIGN;
  158. else
  159. size += BYTES_PER_WORD;
  160. }
  161. #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
  162. if (size >= malloc_sizes[INDEX_L3 + 1].cs_size
  163. && cachep->obj_size > cache_line_size() && ALIGN(size, align) < PAGE_SIZE) {
  164. cachep->obj_offset += PAGE_SIZE - ALIGN(size, align);
  165. size = PAGE_SIZE;
  166. }
  167. #endif
  168. #endif
  169. /*
  170. * Determine if the slab management is 'on' or 'off' slab.
  171. * (bootstrapping cannot cope with offslab caches so don't do
  172. * it too early on.)
  173. */
  174. /*如果緩存對象的大小不小於頁面大小的1/8並且不處於slab初始化階段,
  175. 則選擇將slab描述符放在slab外部以騰出更多的空間給對象*/
  176. if ((size >= (PAGE_SIZE >> 3)) && !slab_early_init)
  177. /*
  178. * Size is large, assume best to place the slab management obj
  179. * off-slab (should allow better packing of objs).
  180. */
  181. flags |= CFLGS_OFF_SLAB;
  182. /*將對象大小按之前確定的align對齊*/
  183. size = ALIGN(size, align);
  184. /*計算slab的對象數,分配給slab的頁框階數並返回slab的剩余空間,即碎片大小*/
  185. left_over = calculate_slab_order(cachep, size, align, flags);
  186. if (!cachep->num) {
  187. printk(KERN_ERR
  188. "kmem_cache_create: couldn't create cache %s.\n", name);
  189. kmem_cache_free(&cache_cache, cachep);
  190. cachep = NULL;
  191. goto oops;
  192. }
  193. /*將slab管理區的大小按align進行對齊*/
  194. slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t)
  195. + sizeof(struct slab), align);
  196. /*
  197. * If the slab has been placed off-slab, and we have enough space then
  198. * move it on-slab. This is at the expense of any extra colouring.
  199. */
  200. /*如果之前確定將slab管理區放在slab外部,但是碎片空間大於slab管理區大小,
  201. 這時改變策略將slab管理區放在slab內部,這樣可以節省外部空間,但是會犧牲
  202. 著色的顏色個數*/
  203. if (flags & CFLGS_OFF_SLAB && left_over >= slab_size) {
  204. flags &= ~CFLGS_OFF_SLAB;
  205. left_over -= slab_size;
  206. }
  207. /*如果的確要將slab管理區放在外部,則不需按照該slab的對齊方式進行對齊了,
  208. 重新計算slab_size*/
  209. if (flags & CFLGS_OFF_SLAB) {
  210. /* really off slab. No need for manual alignment */
  211. slab_size =
  212. cachep->num * sizeof(kmem_bufctl_t) + sizeof(struct slab);
  213. #ifdef CONFIG_PAGE_POISONING
  214. /* If we're going to use the generic kernel_map_pages()
  215. * poisoning, then it's going to smash the contents of
  216. * the redzone and userword anyhow, so switch them off.
  217. */
  218. if (size % PAGE_SIZE == 0 && flags & SLAB_POISON)
  219. flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
  220. #endif
  221. }
  222. /*著色偏移區L1緩���行的大小*/
  223. cachep->colour_off = cache_line_size();
  224. /* Offset must be a multiple of the alignment. */
  225. if (cachep->colour_off < align)/*著色偏移小於align的話則要取對齊值*/
  226. cachep->colour_off = align;
  227. /*計算著色的顏色數目*/
  228. cachep->colour = left_over / cachep->colour_off;
  229. cachep->slab_size = slab_size;
  230. cachep->flags = flags;
  231. cachep->gfpflags = 0;
  232. if (CONFIG_ZONE_DMA_FLAG && (flags & SLAB_CACHE_DMA))
  233. cachep->gfpflags |= GFP_DMA;
  234. cachep->buffer_size = size;
  235. cachep->reciprocal_buffer_size = reciprocal_value(size);
  236. if (flags & CFLGS_OFF_SLAB) {
  237. cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);
  238. /*
  239. * This is a possibility for one of the malloc_sizes caches.
  240. * But since we go off slab only for object size greater than
  241. * PAGE_SIZE/8, and malloc_sizes gets created in ascending order,
  242. * this should not happen at all.
  243. * But leave a BUG_ON for some lucky dude.
  244. */
  245. BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache));
  246. }
  247. cachep->ctor = ctor;
  248. cachep->name = name;
  249. if (setup_cpu_cache(cachep, gfp)) {
  250. __kmem_cache_destroy(cachep);
  251. cachep = NULL;
  252. goto oops;
  253. }
  254. /* cache setup completed, link it into the list */
  255. /*將該高速緩存描述符添加進cache_chain*/
  256. list_add(&cachep->next, &cache_chain);
  257. oops:
  258. if (!cachep && (flags & SLAB_PANIC))
  259. panic("kmem_cache_create(): failed to create slab `%s'\n",
  260. name);
  261. if (slab_is_available()) {
  262. mutex_unlock(&cache_chain_mutex);
  263. put_online_cpus();
  264. }
  265. return cachep;
  266. }
Copyright © Linux教程網 All Rights Reserved