资讯专栏INFORMATION COLUMN

python 源码笔记 ---- freeblock

xuxueli / 2203人阅读

摘要:首先申请一块大的空间,然后把它切割成一小份,一直到。问题整个过程是一种比较自然的分配方式。但当我读到这段代码时,却感到疑惑指向空闲的链表,为它赋值很好理解。同时,指向原来指向的内容,这是一个很简单的链表插入操作。

1 引言

在python内存管理中,有一个block的概念。它比较类似于SGI次级空间配置器。
首先申请一块大的空间(4KB),然后把它切割成一小份(8, 16 一直到512)。
当有内存申请的请求时候,简单的流程是:根据大小找到对应的block,然后在freeblock 上给它一份。

2 问题

整个过程是一种比较自然的slab分配方式。但当我读到这段代码时,却感到疑惑:

static void* _PyObject_Malloc(void* ctx, size_t nbytes)
{
        ...
    pool->freeblock = (block*)pool +  pool->nextoffset;

        pool->nextoffset += INDEX2SIZE(size);
        *(block **)(pool->freeblock) = NULL; // [1]
        ...
}

freeblock指向空闲的链表,为它赋值很好理解。但是为什么要加上代码1处那一句!
对C比较熟悉的童鞋很容易能看出它的作用,它在为*freeblock赋值为NULL。

但是为什么要这么做?
直到看到内存回收的代码:

static void _PyObject_Free(void* ctx, void*p)
{
    ...
    *(block**)p = lastfree = pool->freeblock;
    pool->freeblock = (block*)p;
    ...
}

回想一下SGI次级空间配置,它需要一个链表,指向block中可用的小块。因为这些快,是离散的,只有用指针才能索引它。
在SGI次级空间配置中,是用一个union,达到了节省空间的目的:有数据时,它存储着真正的数据;没有数据时,它就变成指向下一块可用内存的指针:

union __Obj {
    union __Obj* free_list_link;
    char client_data[];
};

这样一想,问题就变得很明显了。freeblock指向一个链表,链表的next域就由它自己来索引。
在_PyObject_Free中,内存p是要被回收的,它应该插在freeblock的链表头,freeblock被更新指向它。同时,p指向原来freeblock指向的内容,这是一个很简单的链表插入操作。
这样在遍历的时候,我们就可以用freeblock = * freeblock的方式来工作了。
如下图所示:

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/37526.html

相关文章

  • 回归本质-Python源码剖析学习笔记(0)

    1. python整体架构 showImg(https://segmentfault.com/img/bVbkSUT?w=857&h=481); 2. 源代码文件组织 showImg(https://segmentfault.com/img/bVbkSYB?w=347&h=532); 3. 源码编译

    Code4App 评论0 收藏0
  • gevent 学习笔记 —— greenlet源码剖析1

    摘要:不过不管怎样,就当多学习了一些其他知识,况且分析源码肯定少不了对这些知识的了解。官方文档描述里面提到了,在这个模块中指的就是,一般称它为方法列表。返回一个指向它创建的模块对象的指针。 showImg(http://young-py.github.io/imgs/yyzt3.jpg); 在greenlet篇中只是简单讲述了一下greenlet原理,不知道有没有人对源码感兴趣的,不过我还...

    lookSomeone 评论0 收藏0

发表评论

0条评论

xuxueli

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<