Linux Slub分配器(六)--slab的分配与释放
来源:互联网 发布:nginx 系统 日志 编辑:程序博客网 时间:2024/05/02 04:51
水平有限,描述不当之处还请之处,转载请注明出处http://blog.csdn.net/vanbreaker/article/details/7702677
创建新的slab主要有两个工作,一个是从伙伴系统分配2^order个连续页框给该slab,然后就是划分slab中的对象。
函数new_slab()用来创建一个新的slab.
- <SPAN style="FONT-SIZE: 12px">static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
- {
- struct page *page;
- void *start;
- void *last;
- void *p;
- BUG_ON(flags & GFP_SLAB_BUG_MASK);
- /*为待创建的slab分配页框*/
- page = allocate_slab(s,
- flags & (GFP_RECLAIM_MASK | GFP_CONSTRAINT_MASK), node);
- if (!page)
- goto out;
- /*增加slab计数*/
- inc_slabs_node(s, page_to_nid(page), page->objects);
- page->slab = s;//设置页描述符的slab指针
- page->flags |= 1 << PG_slab;//为页框增加一个slab属性
- if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON |
- SLAB_STORE_USER | SLAB_TRACE))
- __SetPageSlubDebug(page);
- /*获取页框的虚拟地址*/
- start = page_address(page);
- if (unlikely(s->flags & SLAB_POISON))
- memset(start, POISON_INUSE, PAGE_SIZE << compound_order(page));
- last = start;
- for_each_object(p, s, start, page->objects) {
- setup_object(s, page, last);//调用构造函数
- set_freepointer(s, last, p); //设置空闲指针,即last后面的空闲对象为p
- last = p;
- }
- setup_object(s, page, last);
- set_freepointer(s, last, NULL); //最后一个对象的空闲指针设为NULL
- /*设置page的freelist和inuse*/
- page->freelist = start;
- page->inuse = 0;
- out:
- return page;
- }</SPAN>
<span style="font-size:12px;">static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node){struct page *page;void *start;void *last;void *p;BUG_ON(flags & GFP_SLAB_BUG_MASK);/*为待创建的slab分配页框*/page = allocate_slab(s,flags & (GFP_RECLAIM_MASK | GFP_CONSTRAINT_MASK), node);if (!page)goto out; /*增加slab计数*/inc_slabs_node(s, page_to_nid(page), page->objects);page->slab = s;//设置页描述符的slab指针page->flags |= 1 << PG_slab;//为页框增加一个slab属性if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON |SLAB_STORE_USER | SLAB_TRACE))__SetPageSlubDebug(page);/*获取页框的虚拟地址*/start = page_address(page);if (unlikely(s->flags & SLAB_POISON))memset(start, POISON_INUSE, PAGE_SIZE << compound_order(page));last = start;for_each_object(p, s, start, page->objects) {setup_object(s, page, last);//调用构造函数set_freepointer(s, last, p); //设置空闲指针,即last后面的空闲对象为plast = p;}setup_object(s, page, last);set_freepointer(s, last, NULL); //最后一个对象的空闲指针设为NULL/*设置page的freelist和inuse*/page->freelist = start;page->inuse = 0;out:return page;}</span>
- <SPAN style="FONT-SIZE: 12px">static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
- {
- struct page *page;
- struct kmem_cache_order_objects oo = s->oo;
- gfp_t alloc_gfp;
- flags |= s->allocflags;
- /*
- * Let the initial higher-order allocation fail under memory pressure
- * so we fall-back to the minimum order allocation.
- */
- /*确定gfp标识*/
- alloc_gfp = (flags | __GFP_NOWARN | __GFP_NORETRY) & ~__GFP_NOFAIL;
- /*分配页框*/
- page = alloc_slab_page(alloc_gfp, node, oo);
- /*如果分配失败,则按min的标准进行分配*/
- if (unlikely(!page)) {
- oo = s->min;
- /*
- * Allocation may have failed due to fragmentation.
- * Try a lower order alloc if possible
- */
- page = alloc_slab_page(flags, node, oo);
- if (!page)
- return NULL;
- stat(get_cpu_slab(s, raw_smp_processor_id()), ORDER_FALLBACK);
- }
- if (kmemcheck_enabled
- && !(s->flags & (SLAB_NOTRACK | DEBUG_DEFAULT_FLAGS))) {
- int pages = 1 << oo_order(oo);
- kmemcheck_alloc_shadow(page, oo_order(oo), flags, node);
- /*
- * Objects from caches that have a constructor don't get
- * cleared when they're allocated, so we need to do it here.
- */
- if (s->ctor)
- kmemcheck_mark_uninitialized_pages(page, pages);
- else
- kmemcheck_mark_unallocated_pages(page, pages);
- }
- page->objects = oo_objects(oo);//从oo中提取出slab中的对象数放到保存到page的objects中
- mod_zone_page_state(page_zone(page),
- (s->flags & SLAB_RECLAIM_ACCOUNT) ?
- NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
- 1 << oo_order(oo));
- return page;
- }</SPAN>
<span style="font-size:12px;">static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node){struct page *page;struct kmem_cache_order_objects oo = s->oo;gfp_t alloc_gfp;flags |= s->allocflags;/* * Let the initial higher-order allocation fail under memory pressure * so we fall-back to the minimum order allocation. */ /*确定gfp标识*/alloc_gfp = (flags | __GFP_NOWARN | __GFP_NORETRY) & ~__GFP_NOFAIL;/*分配页框*/page = alloc_slab_page(alloc_gfp, node, oo);/*如果分配失败,则按min的标准进行分配*/if (unlikely(!page)) {oo = s->min;/* * Allocation may have failed due to fragmentation. * Try a lower order alloc if possible */page = alloc_slab_page(flags, node, oo);if (!page)return NULL;stat(get_cpu_slab(s, raw_smp_processor_id()), ORDER_FALLBACK);}if (kmemcheck_enabled&& !(s->flags & (SLAB_NOTRACK | DEBUG_DEFAULT_FLAGS))) {int pages = 1 << oo_order(oo);kmemcheck_alloc_shadow(page, oo_order(oo), flags, node);/* * Objects from caches that have a constructor don't get * cleared when they're allocated, so we need to do it here. */if (s->ctor)kmemcheck_mark_uninitialized_pages(page, pages);elsekmemcheck_mark_unallocated_pages(page, pages);}page->objects = oo_objects(oo);//从oo中提取出slab中的对象数放到保存到page的objects中mod_zone_page_state(page_zone(page),(s->flags & SLAB_RECLAIM_ACCOUNT) ?NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,1 << oo_order(oo));return page;}</span>
函数alloc_slab_page()便是Slub分配器与伙伴系统的接口!
- <SPAN style="FONT-SIZE: 12px">static inline struct page *alloc_slab_page(gfp_t flags, int node,
- struct kmem_cache_order_objects oo)
- {
- int order = oo_order(oo);//从oo中提取出分配阶数
- flags |= __GFP_NOTRACK;
- /*从伙伴系统中分配2^order个连续页框*/
- if (node == -1)
- return alloc_pages(flags, order);
- else
- return alloc_pages_node(node, flags, order);
- }
- </SPAN>
<span style="font-size:12px;">static inline struct page *alloc_slab_page(gfp_t flags, int node,struct kmem_cache_order_objects oo){int order = oo_order(oo);//从oo中提取出分配阶数flags |= __GFP_NOTRACK;/*从伙伴系统中分配2^order个连续页框*/if (node == -1)return alloc_pages(flags, order);elsereturn alloc_pages_node(node, flags, order);}</span>
获得了所需的页框后,接下来就是在这些页框中划分对象,将他们全部组织起来
- <SPAN style="FONT-SIZE: 12px">for_each_object(p, s, start, page->objects) {
- setup_object(s, page, last);//调用构造函数
- set_freepointer(s, last, p); //设置空闲指针,即last后面的空闲对象为p
- last = p;
- }
- </SPAN>
<span style="font-size:12px;">for_each_object(p, s, start, page->objects) {setup_object(s, page, last);//调用构造函数set_freepointer(s, last, p); //设置空闲指针,即last后面的空闲对象为plast = p;}</span>
- <SPAN style="FONT-SIZE: 12px">#define for_each_object(__p, __s, __addr, __objects) \
- for (__p = (__addr); __p < (__addr) + (__objects) * (__s)->size;\
- __p += (__s)->size)
- </SPAN>
<span style="font-size:12px;">#define for_each_object(__p, __s, __addr, __objects) \for (__p = (__addr); __p < (__addr) + (__objects) * (__s)->size;\__p += (__s)->size)</span>
- <SPAN style="FONT-SIZE: 12px">static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
- {
- /*注意kmem_cache中的offset是以字节为单位的*/
- *(void **)(object + s->offset) = fp;
- }
- </SPAN>
<span style="font-size:12px;">static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp){/*注意kmem_cache中的offset是以字节为单位的*/*(void **)(object + s->offset) = fp;}</span>
初始化后的对象如下图所示
销毁slab通过函数discard_slab()来完成
- <SPAN style="FONT-SIZE: 12px">static void discard_slab(struct kmem_cache *s, struct page *page)
- {
- /*减少节点的slab计数和对象计数*/
- dec_slabs_node(s, page_to_nid(page), page->objects);
- free_slab(s, page);//释放slab
- }</SPAN>
<span style="font-size:12px;">static void discard_slab(struct kmem_cache *s, struct page *page){/*减少节点的slab计数和对象计数*/dec_slabs_node(s, page_to_nid(page), page->objects);free_slab(s, page);//释放slab}</span>
- <SPAN style="FONT-SIZE: 12px">static void free_slab(struct kmem_cache *s, struct page *page)
- {
- if (unlikely(s->flags & SLAB_DESTROY_BY_RCU)) {
- /*
- * RCU free overloads the RCU head over the LRU
- */
- struct rcu_head *head = (void *)&page->lru;
- call_rcu(head, rcu_free_slab);//通过RCU方式来释放
- } else
- __free_slab(s, page);//将slab所占页框释放回伙伴系统
- }
- </SPAN>
<span style="font-size:12px;">static void free_slab(struct kmem_cache *s, struct page *page){if (unlikely(s->flags & SLAB_DESTROY_BY_RCU)) {/* * RCU free overloads the RCU head over the LRU */struct rcu_head *head = (void *)&page->lru;call_rcu(head, rcu_free_slab);//通过RCU方式来释放} else__free_slab(s, page);//将slab所占页框释放回伙伴系统}</span>
0 0
- Linux Slub分配器(六)--slab的分配与释放
- Linux Slub分配器(六)--slab的分配与释放
- Linux Slub分配器(六)--slab的分配与释放
- linux的最新slab分配器---slub分配器
- Linux SLUB分配器之三(释放对象的代码分析)
- Linux Slub分配器(五)--释放对象
- Linux Slub分配器(五)--释放对象 .
- Linux Slub分配器(五)--释放对象
- Linux内存分配机制:SLAB / SLUB / SLOB
- Linux的slab分配器
- Linux Slub分配器(四)--分配对象
- Linux Slub分配器(四)--分配对象
- Linux Slub分配器(四)--分配对象
- Linux内核内存管理之SLAB内存管理算法(三) --slab对象的分配与释放
- Linux Slab分配器(六)--创建slab和销毁slab
- Linux Slab分配器(五)--释放对象
- Linux中的内存分配和释放之slab分配器分析(完)
- Linux Slab分配器(四)--分配对象
- SearchView
- opencv实现图像邻域均值滤波、中值滤波、高斯滤波
- Windows下的修改Tomcat的可用内存
- .net Global中的所有事件
- 黑马程序员_对象的简单分析_对象与函数参数_常见错误
- Linux Slub分配器(六)--slab的分配与释放
- 关于Oracle SQL性能优化
- 地方很多染头发和为贵
- GFS中的数据完整性校验
- 少写了 @ResponseBody 引发的古怪问题
- 数据泡沫该如何面对
- 谈一谈二次空气喷射泵在汽车中具体应用
- Linux如何查看进程、杀死进程、启动进程等常用命令
- Linux Slub分配器(七)--销毁缓存