摘要:首先申請一塊大的空間,然后把它切割成一小份,一直到。問題整個過程是一種比較自然的分配方式。但當我讀到這段代碼時,卻感到疑惑指向空閑的鏈表,為它賦值很好理解。同時,指向原來指向的內容,這是一個很簡單的鏈表插入操作。
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的方式來工作了。
如下圖所示:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/37526.html
1. python整體架構 showImg(https://segmentfault.com/img/bVbkSUT?w=857&h=481); 2. 源代碼文件組織 showImg(https://segmentfault.com/img/bVbkSYB?w=347&h=532); 3. 源碼編譯
摘要:不過不管怎樣,就當多學習了一些其他知識,況且分析源碼肯定少不了對這些知識的了解。官方文檔描述里面提到了,在這個模塊中指的就是,一般稱它為方法列表。返回一個指向它創建的模塊對象的指針。 showImg(http://young-py.github.io/imgs/yyzt3.jpg); 在greenlet篇中只是簡單講述了一下greenlet原理,不知道有沒有人對源碼感興趣的,不過我還...
閱讀 1267·2023-04-25 23:22
閱讀 1668·2023-04-25 20:04
閱讀 2643·2021-11-22 15:24
閱讀 2801·2021-11-11 16:54
閱讀 1879·2019-08-30 14:03
閱讀 1480·2019-08-29 16:35
閱讀 1700·2019-08-26 10:29
閱讀 2643·2019-08-23 18:01