`
tomhibolu
  • 浏览: 1431469 次
文章分类
社区版块
存档分类
最新评论

kernel hacker修炼之道之内存管理-SLAB(创建SLAB块cache_grow())

 
阅读更多

创建SLAB高速缓存cache_grow() 作者:李万鹏 于北京 borqs


从buddy system给cache分配新的slab。


static int cache_grow (kmem_cache_t * cachep, int flags, int nodeid)
{
struct slab *slabp;
void *objp;
size_t offset;
int local_flags;
unsigned long ctor_flags;

/* Be lazy and only check for valid flags here,
* keeping it out of the critical path in kmem_cache_alloc().
*/
if (flags & ~(SLAB_DMA|SLAB_LEVEL_MASK|SLAB_NO_GROW))
BUG();
if (flags & SLAB_NO_GROW)
return 0;

ctor_flags = SLAB_CTOR_CONSTRUCTOR;
local_flags = (flags & SLAB_LEVEL_MASK);
if (!(local_flags & __GFP_WAIT))
/*
* Not allowed to sleep. Need to tell a constructor about
* this - it might need to know...
*/
ctor_flags |= SLAB_CTOR_ATOMIC;

/* About to mess with non-constant members - lock. */
check_irq_off();
spin_lock(&cachep->spinlock);

/* Get colour for the slab, and cal the next value. */
/*获得颜色*/
offset = cachep->colour_next;
/*获得下一个颜色*/
cachep->colour_next++;
if (cachep->colour_next >= cachep->colour)
cachep->colour_next = 0;
/*得到偏移量*/
offset *= cachep->colour_off;
spin_unlock(&cachep->spinlock);
if (local_flags & __GFP_WAIT)
local_irq_enable();
/*
* The test for missing atomic flag is performed here, rather than
* the more obvious place, simply to reduce the critical path length
* in kmem_cache_alloc(). If a caller is seriously mis-behaving they
* will eventually be caught here (where it matters).
*/
kmem_flagcheck(cachep, flags);
/*获得slab对应的物理页*/
if (!(objp = kmem_getpages(cachep, flags, nodeid)))
goto failed;
/*获得slab描述符*/
if (!(slabp = alloc_slabmgmt(cachep, objp, offset, local_flags)))
goto opps1;
/*设置属性*/
set_slab_attr(cachep, slabp, objp);
/*初始化slab中的对象*/
cache_init_objs(cachep, slabp, ctor_flags);

if (local_flags & __GFP_WAIT)
local_irq_disable();
check_irq_off();
spin_lock(&cachep->spinlock);

/*将新分配的slab添加到slabs_free*/
list_add_tail(&slabp->list, &(list3_data(cachep)->slabs_free));
STATS_INC_GROWN(cachep);
list3_data(cachep)->free_objects += cachep->num;
spin_unlock(&cachep->spinlock);
return 1;
opps1:
kmem_freepages(cachep, objp);
failed:
if (local_flags & __GFP_WAIT)
local_irq_disable();
return 0;
}


static void *kmem_getpages(kmem_cache_t *cachep, int flags, int nodeid)
{
struct page *page;
void *addr;
int i;

flags |= cachep->gfpflags;
/*如果没有指定节点,则从本节点分配*/
if (likely(nodeid == -1)) {
page = alloc_pages(flags, cachep->gfporder);
} else {
/*如果指定了节点,则从指定的节点分配*/
page = alloc_pages_node(nodeid, flags, cachep->gfporder);
}
if (!page)
return NULL;
/*获得slab第一个页的线性地址*/
addr = page_address(page);
/*获得物理页的数量*/
i = (1 << cachep->gfporder);
if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
atomic_add(i, &slab_reclaim_pages);
add_page_state(nr_slab, i);
/*设置每页的标志位为slab的*/
while (i--) {
SetPageSlab(page);
page++;
}
return addr;
}

static struct slab* alloc_slabmgmt (kmem_cache_t *cachep,
void *objp, int colour_off, int local_flags)
{
struct slab *slabp;
/*如果内存描述符是外置的*/
if (OFF_SLAB(cachep)) {
/*则从在kmem_cache_create()中指定的cache中分配*/
slabp = kmem_cache_alloc(cachep->slabp_cache, local_flags);
if (!slabp)
return NULL;
} else {
slabp = objp+colour_off;
colour_off += cachep->slab_size;
}
slabp->inuse = 0;
slabp->colouroff = colour_off;
slabp->s_mem = objp+colour_off;

return slabp;
}

static void set_slab_attr(kmem_cache_t *cachep, struct slab *slabp, void *objp)
{
int i;
struct page *page;

/* Nasty!!!!!! I hope this is OK. */
i = 1 << cachep->gfporder;
/*获得对象的第一个页的页描述符*/
page = virt_to_page(objp);
do {
/*将高速缓存描述符赋给页描述符中lru字段的next字段*/
SET_PAGE_CACHE(page, cachep);
/*将slab描述符赋给页描述符中lru字段的prev字段*/
SET_PAGE_SLAB(page, slabp);
page++;
} while (--i);
}

static void cache_init_objs (kmem_cache_t * cachep,
struct slab * slabp, unsigned long ctor_flags)
{
int i;

for (i = 0; i < cachep->num; i++) {
/*获得slab中每个对象的地址*/
void* objp = slabp->s_mem+cachep->objsize*i;
#if DEBUG
/* need to poison the objs? */
if (cachep->flags & SLAB_POISON)
poison_obj(cachep, objp, POISON_FREE);
if (cachep->flags & SLAB_STORE_USER)
*dbg_userword(cachep, objp) = NULL;

if (cachep->flags & SLAB_RED_ZONE) {
*dbg_redzone1(cachep, objp) = RED_INACTIVE;
*dbg_redzone2(cachep, objp) = RED_INACTIVE;
}
/*
* Constructors are not allowed to allocate memory from
* the same cache which they are a constructor for.
* Otherwise, deadlock. They must also be threaded.
*/
if (cachep->ctor && !(cachep->flags & SLAB_POISON))
cachep->ctor(objp+obj_dbghead(cachep), cachep, ctor_flags);

if (cachep->flags & SLAB_RED_ZONE) {
if (*dbg_redzone2(cachep, objp) != RED_INACTIVE)
slab_error(cachep, "constructor overwrote the"
" end of an object");
if (*dbg_redzone1(cachep, objp) != RED_INACTIVE)
slab_error(cachep, "constructor overwrote the"
" start of an object");
}
if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep) && cachep->flags & SLAB_POISON)
kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE, 0);
#else /*调用构造函数初始化每一个对象*/
if (cachep->ctor)
cachep->ctor(objp, cachep, ctor_flags);
#endif
/*指向下一个空闲对象*/
slab_bufctl(slabp)[i] = i+1;
}
slab_bufctl(slabp)[i-1] = BUFCTL_END;
slabp->free = 0;
}

分享到:
评论

相关推荐

    Linux常见驱动源码分析(kernel hacker修炼之道全集)--李万鹏

    Linux常见驱动源码分析(kernel hacker修炼之道)--李万鹏 李万鹏 IBM Linux Technology Center kernel team 驱动资料清单内容如下: Linux设备模型(中)之上层容器.pdf Linux设备模型(上)之底层模型.pdf Linux...

    常见驱动源码分析(kernel hacker修炼之道)-李万鹏

    这本书是“Linux kernel hacker修炼之道”的一部分,通过深入剖析各种常见的驱动源码,帮助读者提升在Linux系统中的驱动开发能力。 在Linux操作系统中,驱动程序是连接硬件与内核的桥梁,它们负责管理和控制硬件...

    常见驱动源码分析(kernel hacker修炼之道)

    《常见驱动源码分析(kernel hacker修炼之道)》这本书或课程很可能深入探讨了如何理解和编写这些驱动,旨在帮助开发者提升对Linux内核和驱动编程的理解。在这个过程中,我们将会涉及到几个关键的知识点: 1. **Linux...

    网鼎杯-第三场-杂项-track_hacker

    【网鼎杯-第三场-杂项-track_hacker】是一个典型的网络安全竞赛中的挑战,涉及到的是CTF(Capture The Flag)比赛中的杂项类别。在CTF比赛中,参赛者需要运用各种安全技能解决难题,获取“旗标”(代表分数或解题...

    Resource_Hacker_v5.1.6绿色版.zip

    资源 Hacker 是一款强大的Windows应用程序资源编辑工具,主要用于查看、修改、添加、删除以及替换应用程序中的资源,如图标、对话框、菜单、字符串表等。在本文中,我们将深入探讨Resource Hacker的功能、使用方法...

    linux kernel修炼之道

    如果刚刚对linux的kernel有兴趣,想了解点什么的话,请先看看此书吧,她风趣幽默的介绍了linux的发展趣事,让你开心快乐之余慢慢领会linux的魅力,让你了解学习掌握kernel的方法。其中的很多建议经过我的实践和摸索...

    HackerRank_2019-2018_Developer-Skills-Report.pdf

    这份标题为"HackerRank_2019-2018_Developer-Skills-Report.pdf"的报告,即HackerRank发布的2019-2018开发者技能报告,详细地探讨了开发者社区中的技术趋势和技能发展情况。根据描述,报告提出了React、物联网(IOT)...

    x64_processhacker_源码

    Process Hacker是一款开源、免费且功能强大的系统信息工具,它允许用户查看并管理正在运行的进程、服务、线程以及内存等系统资源。 【描述】"Process Hacker 1.1 PH1" 提示我们这是Process Hacker的早期版本,版本...

    BotnetWebSocket-master_chancexvw_hacker_websocket_botnet_sangerp

    【标题解析】:“BotnetWebSocket-master_chancexvw_hacker_websocket_botnet_sangerp”这个标题中的关键词“BotnetWebSocket-master”暗示了一个与僵尸网络(Botnet)相关的项目,特别是利用WebSocket协议的。...

    Linux内核驱动笔记

    内存管理负责分配、回收内存资源,管理虚拟内存和物理内存的映射关系,并实现内存保护机制。 Linux内核支持多种文件系统,例如ext2、fat、isofs等。虚拟文件系统(VFS)是Linux内核中的一个重要概念,它为不同文件...

    leetcode和oj-Leet_Code-Hacker_Rank:Leet_Code-Hacker_Rank

    《LeetCode与Hacker Rank:在线编程挑战的宝库》 LeetCode和Hacker Rank是两个备受程序员喜爱的在线编程挑战平台,它们为提升技能、准备面试和了解最新技术趋势提供了丰富的资源。这两个平台不仅有助于巩固基础,还...

    Resource_Hacker内存修改_v5.1.5.zip

    Resource Hacker是一款免费查看,修改,添加,删除和重命名,提取Windows可执行文件和资源文件的资源替换工具,Resource Hacker反编译工具是相当于eXeScope的反编译工具,并且有很多方面比eXeScope反编译还强的软件.

    1000_Hacker_Tutorials_2008.rar

    1000_Hacker_Tutorials_2008.rar

    HackerRank-Interview-Preparation-Kit-master.rar

    《HackerRank面试准备套装详解》 HackerRank是一家知名的技术人才招聘平台,它提供了丰富的编程挑战和面试准备资源,帮助求职者提升技术能力并熟悉面试流程。"HackerRank-Interview-Preparation-Kit-master"是这个...

    ResourceHacker_V3.5.2_XiaZaiBa.exe

    ResourceHacker_V3.5.2_XiaZaiBa.exe

    processhacker-2.39-bin

    ProcessHacker是一款强大的系统信息工具,它提供了进程管理、服务管理、硬件监控、内存查看等多种功能,深受系统管理员和高级用户的喜爱。这个"processhacker-2.39-bin"压缩包很可能包含了ProcessHacker的二进制版本...

    Resource_Hacker_v4.7.34_Stable_Chs_WangSu

    Resource_Hacker_v4.7.34_Stable_Chs_WangSuResource_Hacker_v4.7.34_Stable_Chs_WangSu

    hacker成长之道

    有关hacker 的文章和资料分享给大家

    Cmake-3.22.0-linux-x86_64安装包

    CMake是一款跨平台的构建工具,它用于管理软件构建过程,尤其适合大型项目或包含多个子项目的工程。CMake不依赖于任何特定的构建系统,而是生成本地构建文件(如Unix Makefiles、Visual Studio项目等),然后使用...

Global site tag (gtag.js) - Google Analytics