内核代码阅读(10) - 内核缓冲区的管理slab下

简介: 内核缓冲区的管理slab下

专用缓冲区 kmem_cache_free 缓冲区的释放

static inline void kmem_cache_free_one(kmem_cache_t *cachep, void *objp)
    {
        slab_t* slabp;
        CHECK_PAGE(virt_to_page(objp));
        slabp = GET_PAGE_SLAB(virt_to_page(objp));
        {
                unsigned int objnr = (objp-slabp->s_mem)/cachep->objsize;
                slab_bufctl(slabp)[objnr] = slabp->free;
                slabp->free = objnr;
        }
        STATS_DEC_ACTIVE(cachep);
        if (slabp->inuse-- == cachep->num)
                goto moveslab_partial;
        if (!slabp->inuse)
                goto moveslab_free;
        return;
    moveslab_partial:
        {
                struct list_head *t = cachep->firstnotfull;
                cachep->firstnotfull = &slabp->list;
                if (slabp->list.next == t)
                        return;
                list_del(&slabp->list);
                list_add_tail(&slabp->list, t);
                return;
        }
    moveslab_free:
        {
                struct list_head *t = cachep->firstnotfull->prev;
                list_del(&slabp->list);
                list_add_tail(&slabp->list, &cachep->slabs);
                if (cachep->firstnotfull == &slabp->list)
                        cachep->firstnotfull = t->next;
                return;
        }
    }
1) slabp = GET_PAGE_SLAB(virt_to_page(objp));
   通过要释放的物理地址,可以获取到对应的 struct page结构, 通过page结构的list可以找到objp所属的slab。
2) unsigned int objnr = (objp-slabp->s_mem)/cachep->objsize;
   slab_bufctl(slabp)[objnr] = slabp->free;
   计算objp在slab中的下标。
   更新slab中的空闲链接数组。
3) if (slabp->inuse-- == cachep->num)
           goto moveslab_partial;
   更新inuse计数器。

通用缓冲区的分配 kmalloc

void * kmalloc (size_t size, int flags)
    {
        cache_sizes_t *csizep = cache_sizes;
        for (; csizep->cs_size; csizep++) {
                if (size > csizep->cs_size)
                        continue;
                return __kmem_cache_alloc(flags & GFP_DMA ?
                         csizep->cs_dmacachep : csizep->cs_cachep, flags);
        }
        return NULL;
    }
1) cache_sizes 是一个cache_sizes_t的结构数组。
   typedef struct cache_sizes {
       size_t                 cs_size;
       kmem_cache_t        *cs_cachep;
       kmem_cache_t        *cs_dmacachep;
   } cache_sizes_t;
2) for 寻转在cache_sizes数组中找到第一个 csizep->cs_size大于size的kmem_cache_t类型的指针。
3) 然后通过 kmem_cache_alloc 分配。

kmem_cache_reap slab的回收

void kmem_cache_reap(int gfp_mask)
    {
        searchp = clock_searchp;
        do {
                unsigned int pages;
                struct list_head* p;
                unsigned int full_free;
                if (searchp->flags & SLAB_NO_REAP)
                        goto next;
                spin_lock_irq(&searchp->spinlock);
                if (searchp->growing)
                        goto next_unlock;
                if (searchp->dflags & DFLGS_GROWN) {
                        searchp->dflags &= ~DFLGS_GROWN;
                        goto next_unlock;
                }
                full_free = 0;
                p = searchp->slabs.prev;
                while (p != &searchp->slabs) {
                        slabp = list_entry(p, slab_t, list);
                        if (slabp->inuse)
                                break;
                        full_free++;
                        p = p->prev;
                }
                pages = full_free * (1<<searchp->gfporder);
                if (searchp->ctor)
                        pages = (pages*4+1)/5;
                if (searchp->gfporder)
                        pages = (pages*4+1)/5;
                if (pages > best_pages) {
                        best_cachep = searchp;
                        best_len = full_free;
                        best_pages = pages;
                        if (full_free >= REAP_PERFECT) {
                                clock_searchp = list_entry(searchp->next.next,
                                                        kmem_cache_t,next);
                                goto perfect;
                        }
                }
                searchp = list_entry(searchp->next.next,kmem_cache_t,next);
        } while (--scan && searchp != clock_searchp);
        clock_searchp = searchp;
        if (!best_cachep)
                goto out;
        spin_lock_irq(&best_cachep->spinlock);
    perfect:
        best_len = (best_len*4 + 1)/5;
        for (scan = 0; scan < best_len; scan++) {
                struct list_head *p;
                if (best_cachep->growing)
                        break;
                p = best_cachep->slabs.prev;
                if (p == &best_cachep->slabs)
                        break;
                slabp = list_entry(p,slab_t,list);
                if (slabp->inuse)
                        break;
                list_del(&slabp->list);
                if (best_cachep->firstnotfull == &slabp->list)
                        best_cachep->firstnotfull = &best_cachep->slabs;
                STATS_INC_REAPED(best_cachep);
                spin_unlock_irq(&best_cachep->spinlock);
                kmem_slab_destroy(best_cachep, slabp);
                spin_lock_irq(&best_cachep->spinlock);
        }
        spin_unlock_irq(&best_cachep->spinlock);
    out:
        up(&cache_chain_sem);
        return;
    }
1) searchp = clock_searchp;
   并不是每次扫描所有的slab队列。clock_searchp 会记住上一次扫描的位置。
2) kmem_slab_destroy(best_cachep, slabp);
相关文章
|
缓存 Android开发
【Android 电量优化】电量优化 ( 网络状态获取 | 主动获取 WIFI 状态 | 被动获取 WIFI 状态 )
【Android 电量优化】电量优化 ( 网络状态获取 | 主动获取 WIFI 状态 | 被动获取 WIFI 状态 )
202 0
|
7天前
|
人工智能 安全 API
CoPaw:5分钟部署你的 AI助理
源自阿里巴巴开源生态的个人 AI 助理——CoPaw。作为阿里倾力打造的开源力作,CoPaw 完美打通钉钉、飞书、Discord 等多平台对话通道,支持定时任务自动化。内置 PDF/Office 深度处理、新闻摘要等强大技能,更开放自定义扩展接口。坚持数据全程私有化部署,绝不上传云端,让每一位用户都能在大厂技术加持下,拥有安全、专属的智能助手。
|
10天前
|
人工智能 自然语言处理 JavaScript
2026年Windows+Ollama本地部署OpenClaw保姆级教程:本地AI Agent+阿里云上快速搭建
2026年OpenClaw凭借本地部署、私有化运行的特性,成为打造个人智能体的核心工具,而Ollama作为轻量级本地大模型管理工具,能让OpenClaw摆脱对云端大模型的依赖,实现**本地推理、数据不泄露、全流程私有化**的智能体验。本文基于Windows 11系统,从硬件环境准备、Ollama安装与模型定制、OpenClaw部署配置、技能扩展到常见问题排查,打造保姆级本地部署教程,同时补充阿里云OpenClaw(Clawdbot)快速部署步骤,兼顾本地私有化需求与云端7×24小时运行需求,文中所有代码命令均可直接复制执行,确保零基础用户也能快速搭建属于自己的本地智能体。
11330 96
|
8天前
|
人工智能 安全 JavaScript
阿里云上+本地部署OpenClaw(小龙虾)新手攻略:解锁10大必备Skills,零基础也能玩转AI助手
2026年,开源AI代理工具OpenClaw(昵称“小龙虾”)凭借“能实际做事”的核心优势,在GitHub斩获25万+星标,成为现象级AI工具。它最强大的魅力在于可扩展的Skills(技能包)系统——通过ClawHub插件市场的数百个技能,能让AI助手从简单聊天升级为处理办公、学习、日常事务的全能帮手。
7326 25
|
6天前
|
人工智能 JavaScript Ubuntu
5分钟上手龙虾AI!OpenClaw部署(阿里云+本地)+ 免费多模型配置保姆级教程(MiniMax、Claude、阿里云百炼)
OpenClaw(昵称“龙虾AI”)作为2026年热门的开源个人AI助手,由PSPDFKit创始人Peter Steinberger开发,核心优势在于“真正执行任务”——不仅能聊天互动,还能自动处理邮件、管理日程、订机票、写代码等,且所有数据本地处理,隐私完全可控。它支持接入MiniMax、Claude、GPT等多类大模型,兼容微信、Telegram、飞书等主流聊天工具,搭配100+可扩展技能,成为兼顾实用性与隐私性的AI工具首选。
5357 10
|
9天前
|
人工智能 自然语言处理 机器人
保姆级教程:Mac本地搭建OpenClaw及阿里云上1分钟部署OpenClaw+飞书集成实战指南
OpenClaw(曾用名Clawdbot、Moltbot)作为2026年最热门的开源个人AI助手平台,以“自然语言驱动自动化”为核心,支持对接飞书、Telegram等主流通讯工具,可替代人工完成文件操作、日历管理、邮件处理等重复性工作。其模块化架构适配多系统环境,既可以在Mac上本地化部署打造私人助手,也能通过阿里云实现7×24小时稳定运行,完美兼顾隐私性与便捷性。
6886 14
|
2天前
|
人工智能 安全 前端开发
Team 版 OpenClaw:HiClaw 开源,5 分钟完成本地安装
HiClaw 基于 OpenClaw、Higress AI Gateway、Element IM 客户端+Tuwunel IM 服务器(均基于 Matrix 实时通信协议)、MinIO 共享文件系统打造。
2864 9
|
4天前
|
人工智能 JavaScript 测试技术
保姆级教程:OpenClaw阿里云及本地部署+Claude Code集成,打造全能 AI 编程助手
在AI编程工具百花齐放的2026年,Anthropic推出的Claude Code凭借72.5%的SWE-bench测试高分、25倍于GitHub Copilot的上下文窗口,成为开发者追捧的智能编程助手。但单一工具仍有局限——Claude Code擅长代码生成与审查,却缺乏灵活的部署与自动化执行能力;而OpenClaw(前身为Clawdbot)作为开源AI代理框架,能完美弥补这一短板,通过云端与本地双部署,实现“代码开发-测试-部署”全流程自动化。
2092 13
|
11天前
|
人工智能 JSON JavaScript
手把手教你用 OpenClaw + 飞书,打造专属 AI 机器人
手把手教你用 OpenClaw(v2026.2.22-2)+ 飞书,10分钟零代码搭建专属AI机器人!内置飞书插件,无需额外安装;支持Claude等主流模型,命令行一键配置。告别复杂开发,像聊同事一样自然对话。
6693 17
手把手教你用 OpenClaw + 飞书,打造专属 AI 机器人

热门文章

最新文章