⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linux-+

📁 linux下内存管理的文章 很长
💻
📖 第 1 页 / 共 4 页
字号:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int gfporder;<br> 
<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* force GFP flags, e.g. GFP_DMA */<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int gfpflags;<br> 
<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t colour; /* cache colouring range */<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int colour_off; /* colour offset  
*/<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int colour_next; /* cache  
colouring */<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kmem_cache_t *slabp_cache;<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int growing;<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int dflags; /* dynamic flags */<br> 
<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* constructor func */<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void (*ctor)(void *, kmem_cache_t *,  
unsigned long);<br> 
<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* de-constructor func */<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void (*dtor)(void *, kmem_cache_t *,  
unsigned long);<br> 
<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long failures;<br> 
<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 3) cache creation/removal */<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char name[CACHE_NAMELEN];<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct list_head next;<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #ifdef CONFIG_SMP<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 4) per-cpu data */<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cpucache_t *cpudata[NR_CPUS];<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endif<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #if STATS<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long num_active;<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long num_allocations;<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long high_mark;<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long grown;<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long reaped;<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long errors;<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #ifdef CONFIG_SMP<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; atomic_t allochit;<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; atomic_t allocmiss;<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; atomic_t freehit;<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; atomic_t freemiss;<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endif<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endif<br> 
};<br> 
</font><br> 
<font color="green">slabs</font>用它将这个cache的slab连成一个链表<br> 
<font color="green">firstnotfull</font>指向第一个不满的slab,当分配(复用)对象的时候,首先考虑在它指向的slab里分配.<br> 
<font color="green">objsize</font>该cache中对象大小<br> 
<font color="green">flags</font><br> 
<font color="green">num</font>对象个数<br> 
<br> 
<font color="green">gfporder</font>该cache中slab一个占用多少页面,当构造新的slab,按照这个大小向页面级分配器申请页面。<br> 
<font color="green">gfpflags</font>申请页面时,向页面级分配器提出的要求,例如是否要求申请DMA的页面,是否要求申请是原子的(即页面分配器在分配的时候不能被阻塞)<br> 
<font color="green">colour&nbsp; </font>colour的范围,这个cache的slab依次用0,1,...,colour-1,0,1,...为颜色。<br> 
<font color="green">colour_off</font>这个cache中colour粒度,例如为一个L1-CACHE线。<br> 
<font color="green">colour_next</font>下一个colour数,当cache分配一个新的slab时,采用这个colour,也就是colour  
* colour_off为slab空出的字节数<br> 
<font color="green">slabp_cache</font><font color="green"> </font>当这个cache中的slab,其管理部分(slab描述符和kmem_bufctl_t数组)放在slab外面时,这个指针指向放置的通用cache<br> 
<font color="green">growing</font><br> 
<font color="green">dflags</font><br> 
<font color="green">ctor</font><font color="green"> </font>指向对象的构造器,在这个cache创建一个新的slab时,对里面所有的对象都进行一次构造调用(参见slab的设计思想中关于对象复用部分)<br> 
<font color="green">dtor</font><font color="green"> </font>指向对象的析构器,在这个cache销毁一个slab时,对里面所有的对象都进行一次析构调用<br> 
<font color="green">failures</font><br> 
<br> 
<font color="green">name</font><font color="green"> </font>这个cache的名字<br> 
<font color="green">next</font><font color="green"> </font>用它和其它的cache串成一个链,在这个链上按照时钟算法定期地回收某个cache的部分slab<br> 
<br> 
<font color="blue"><br> 
slab描述符<br> 
</font><br> 
<font color="green">typedef struct slab_s {<br> 
&nbsp;&nbsp; struct list_head list;<br> 
&nbsp;&nbsp; unsigned long colouroff;<br> 
&nbsp;&nbsp; void *s_mem; /* including colour offset */<br> 
&nbsp;&nbsp; unsigned int inuse; /* num of objs active in slab */<br> 
&nbsp;&nbsp; kmem_bufctl_t free;<br> 
} slab_t;<br> 
</font><br> 
<br> 
<font color="green">list</font>用于链表,这个链表将cache中所有的slab连接起来<br> 
<font color="green">colouroff</font>这个slab中第一个对象距离slab起始位置(也就是页块起始位置)的字节数,实际上s_mem=页块首地址+colouroff<br> 
<font color="green">s_mem</font>这个slab中第一个对象的起始位置<br> 
<font color="green">inuse</font>这个slab中被使用的对象个数,用于调整slab格局,当inuse=0说明这个slab全空,将这个slab从部分满的slab段中移动到全空的slab段中<br> 
<font color="green">free</font>第一个未用对象的ID, 当在这个slab&quot;分配&quot;(复用)对象时,首先用这个ID的对象。<br> 
<br> 
<font color="blue"><br> 
通用cache索引结构<br> 
用这个结构组成的数组cache_sizes给不同尺寸的通用cache提供索引<br> 
</font><font color="green">typedef struct cache_sizes {<br> 
size_t cs_size;<br> 
kmem_cache_t *cs_cachep;<br> 
kmem_cache_t *cs_dmacachep;<br> 
} cache_sizes_t;<br> 
cs_size</font>通用cache的对象尺寸<br> 
<font color="green">cs_cachep</font>指向一个通用cache,  
它的对象尺寸为cs_size<br> 
<font color="green">cs_dmacachep</font>指向一个通用DMA的cache,  
它的对象尺寸为cs_size<br> 
<br> 
<br> 
<br> 
<font color="blue">Slab分配器的结构</font><br> 
<br> 
Slab 分配器用于管理内核的核心对象。<br> 
<br> 
它有若干个 cache 组成。每个 cache 管理一个特定类的对象。<br> 
<br> 
每个cache有若干个 slab (Slab分配器的名字可能就是怎么来的)组成,每个  
slab<br> 
实际上就是若干个页面组成的一个页块。这个页块被细分成许多对象。<br> 
cache为管理这些slab, 通过 cache描述符( kmem_cache_t )以及指针将这些  
slab<br> 
连起来。<br> 
</span></p>                   
<font color="blue">验证</font><br> 
cache的数据结构中下面这个字段:<br> 
struct&nbsp; kmem_cache_s {<br> 
<br> 
struct list_headslabs;<br> 
... ...<br> 
}<br> 
<br> 
与slab结构中下面字段:<br> 
<br> 
typedef struct slab_s {<br> 
struct list_headlist;<br> 
&nbsp;...<br> 
} slab_t;<br> 
<br> 
共同构成这个链表. 
<p><span class="post"><font color="#FF00FF">slab如何管理它的对象</font><br> 
<br> 
一个 slab 通过自己的 kmem_bufctl_t  
数组,来管理它的空闲对象。这个数组的元素和该 slab中的对象是一一对应的。<br> 
</span>初始化一个slab时,每个对象都是空的,所以这个数组每个元素(除最后一个)都指向下一个:<br> 
在kmem_cache_init_objs中<br> 
static inline void kmem_cache_init_objs (kmem_cache_t * cachep, slab_t * slabp,  
unsigned long ctor_flags)<br> 
{<br> 
int i;<br> 
<br> 
for (i = 0; i &lt; cachep-&gt;num; i++) {<br> 
.. ...<br> 
slab_bufctl(slabp)[ i ] = i+1;<br> 
}<br> 
slab_bufctl(slabp)[i-1] = BUFCTL_END;<br> 
... ...<br> 
}<br> 
<br> 
分配对象时,在下面的语句中,<br> 
<br> 
objp = slabp-&gt;s_mem + slabp-&gt;free*cachep-&gt;objsize;<br> 
slabp-&gt;free=slab_bufctl(slabp)[slabp-&gt;free];<br> 
<br> 
取出free的数值1,计算对象1的位置即可。然后将free指向3.<br> 
回收(应该说将对象置为未用)时,将数组中对象对应的元素插入链表头即可:<br> 
slab_bufctl(slabp)[objnr] = slabp-&gt;free;<br> 
slabp-&gt;free = objnr;<br> 
</p> 
<p class="post"><span class="post"><font color="#FF00FF">cache如何管理它的slab</font><br> 
<br> 
<font color="blue">格局</font><br> 
<br> 
一个cache的所有 slab 通过指针连成一个队列,这些 slab的排列始终保持一个格局:  
全满的,部分满的,和全空的。<br> 
另外,cache 描述符有一个指针始终指向第一个不满的slab(首先可能是部分满的,其次是全空的),当它指向描述符本身的时候,说明没有不满的  
slab了。当 slab 是否满的状态有变化时,cache会调整它的位置,以保持上述格局,例如一个部分满的  
slab由于它的最后一个对象被设置为不使用,即它为全空的了,那么它将被调整到全空的slab部分中。<br> 
<br> 
<FONT<BR> 
当分配一个新的对象时,cache 首先通过 firstnotfull  
找到它的第一个不满的slab,  
在那么分配对象。如果没有不满的slab,<br> 
则向页面级分配器申请一个页块,然后初始化为一个slab.<br> 
<br> 
<font color="blue">回收对象</font><br> 
<br> 
当回收一个对象时,即便在这之后,这个对象所在的 slab  
为全空,cache也不会将这个 slab<br> 
占用的页块还给页面级分配器。<br> 
<br> 
<font color="blue">回收slab</font><br> 
<br> 
slab分配器算法提供两种回收slab的方式,一种是回收某个特定的cache的所有全空的slab,直到有用户又在该cache分配新的  
slab为止( kmem_cache_shrink);一种是对所有的 cache  
采用时钟算法,每次选择一个比较合适的 cache,回收它部分的空  
slab( kmem_cache_reap ).<br> 
<br> 
<font color="blue">验证</font><br> 
<br> 
每次分配的时候总是考察从firstnotfull指向的第一个不满的slab:<br> 
#define kmem_cache_alloc_one(cachep) \<br> 
({  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  
\<br> 
slab_t*slabp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \<br> 
/* Get slab alloc is to come from. */ \<br> 
{ \<br> 
struct list_head* p = cachep-&gt;firstnotfull;/*&lt;----------这里*/ \<br> 
if (p == &amp;cachep-&gt;slabs) \<br> 
goto<br> 
&nbsp; alloc_new_slab;/*&lt;---------如果这个指针指向cache了,说明没有不满的slab了,?br&gt;簿褪撬狄

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -