📄 linux设备驱动程序学习(8)-分配内存 - linux设备驱动程序 - tekkaman ninja.htm
字号:
flags<SPAN
style="COLOR: #0000cc">,</SPAN><BR> <SPAN
style="COLOR: #0000ff">void</SPAN> <SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000cc">*</SPAN>constructor<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000ff">void</SPAN> <SPAN
style="COLOR: #0000cc">*</SPAN><SPAN
style="COLOR: #0000cc">,</SPAN> kmem_cache_t
<SPAN style="COLOR: #0000cc">*</SPAN><SPAN
style="COLOR: #0000cc">,</SPAN><SPAN
style="COLOR: #0000ff">unsigned</SPAN> <SPAN
style="COLOR: #0000ff">long</SPAN> flags<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">,</SPAN>
</FONT></SPAN></CODE></P>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: #000000"><FONT face=新宋体><SPAN
style="COLOR: #0000ff"> void</SPAN> <SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000cc">*</SPAN>destructor<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000ff">void</SPAN> <SPAN
style="COLOR: #0000cc">*</SPAN><SPAN
style="COLOR: #0000cc">,</SPAN> kmem_cache_t
<SPAN style="COLOR: #0000cc">*</SPAN><SPAN
style="COLOR: #0000cc">,</SPAN> <SPAN
style="COLOR: #0000ff">unsigned</SPAN> <SPAN
style="COLOR: #0000ff">long</SPAN> flags<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN><BR><SPAN
style="COLOR: #ff9900">/*创建一个可以容纳任意数目内存区域的、大小都相同的高速缓存对象*/</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></FONT></SPAN></FONT></P>
<DT>
<P><FONT color=#000000><SPAN class=term>参数<FONT
face=新宋体><SPAN
style="COLOR: #0000cc">*</SPAN>name:</FONT>
一个指向 name
的指针,name和这个后备高速缓存相关联,功能是管理信息以便追踪问题;通常设置为被缓存的结构类型的名字,不能包含空格。</SPAN></FONT></P>
<DT>
<P><FONT color=#000000><SPAN class=term><SPAN
class=term>参数<FONT
face=新宋体>size:每个内存区域的大小。</FONT></SPAN></SPAN></FONT></P>
<DT>
<P><FONT color=#000000><SPAN class=term><SPAN
class=term><FONT face=新宋体><SPAN class=term><SPAN
class=term><FONT
face="Courier New">参数</FONT></SPAN></SPAN>offset:页内第一个对象的偏移量;用来确保被分配对象的特殊对齐,0
表示缺省值。 </FONT></SPAN></SPAN></FONT></P>
<DT>
<P><FONT color=#0000ff><SPAN class=term><FONT
face=新宋体 color=#000000><SPAN class=term><SPAN
class=term><FONT
face="Courier New">参数</FONT></SPAN></SPAN>flags:控制分配方式的位掩码:</P>
<DIV class=variablelist>
<DL>
<DT><SPAN
class=term><SPAN>SLAB_NO_REAP
</SPAN></SPAN>保护缓存在系统查找内存时不被削减,不推荐。
<DT><SPAN
class=term><SPAN>SLAB_HWCACHE_ALIGN
</SPAN></SPAN>所有数据对象跟高速缓存行对齐,平台依赖,可能浪费内存。
<DT><SPAN
class=term><SPAN>SLAB_CACHE_DMA
</SPAN></SPAN>每个数据对象在 DMA
内存区段分配.</DT></DL></DIV>
<P>其他标志详见 <FONT
color=#0000ff>mm/slab.c</FONT>。但是,通常这些标志在只在开发系统中通过内核配置选项被全局性地设置。</P></FONT></SPAN></FONT></DT></DL>
<DIV>
<P>参数constructor 和 destructor
是可选函数(不能只有destructor,而没有constructor
),用来初始化新分配的对象和在内存被作为整体释放给系统之前“清理”对象。</P>
<P>constructor
函数在分配一组对象的内存时被调用,由于内存可能持有几个对象,所以可能被多次调用。同理,destructor不是立刻在一个对象被释放后调用,而可能在以后某个未知的时间中调用。
根据它们是否被传递 SLAB_CTOR_ATOMIC 标志( CTOR 是 constructor
的缩写),控制是否允许休眠。由于当被调用者是constructor函数时,slab 分配器会传递
SLAB_CTOR_CONSTRUCTOR
标志。为了方便,它们可通过检测这个标志以使用同一函数。</P>
<P>(2)通过调用 kmem_cache_alloc 从已创建的后备高速缓存中分配对象:
<TABLE style="BORDER-COLLAPSE: collapse"
borderColor=#999999 cellSpacing=0 cellPadding=0
width="95%" bgColor=#f1f1f1 border=1>
<TBODY>
<TR>
<TD>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: #000000"><FONT face=新宋体><SPAN
style="COLOR: #0000ff">void</SPAN> <SPAN
style="COLOR: #0000cc">*</SPAN>kmem_cache_alloc<SPAN
style="COLOR: #0000cc">(</SPAN>kmem_cache_t
<SPAN style="COLOR: #0000cc">*</SPAN>cache<SPAN
style="COLOR: #0000cc">,</SPAN> <SPAN
style="COLOR: #0000ff">int</SPAN> flags<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN><BR><SPAN
style="COLOR: #ff9900">/*cache 参数是刚创建缓存,flags
是和kmalloc
的相同*/</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></P>
<P>(3)使用 kmem_cache_free释放一个对象:
<TABLE style="BORDER-COLLAPSE: collapse"
borderColor=#999999 cellSpacing=0 cellPadding=0
width="95%" bgColor=#f1f1f1 border=1>
<TBODY>
<TR>
<TD>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: #000000"><FONT face=新宋体><SPAN
style="COLOR: #0000ff">void</SPAN>
kmem_cache_free<SPAN
style="COLOR: #0000cc">(</SPAN>kmem_cache_t
<SPAN style="COLOR: #0000cc">*</SPAN>cache<SPAN
style="COLOR: #0000cc">,</SPAN> <SPAN
style="COLOR: #0000ff">const</SPAN> <SPAN
style="COLOR: #0000ff">void</SPAN> <SPAN
style="COLOR: #0000cc">*</SPAN>obj<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></P>
<P>(4)当驱动用完这个后备高速缓存(通常在当模块被卸载时),释放缓存:</P>
<P>
<TABLE style="BORDER-COLLAPSE: collapse"
borderColor=#999999 cellSpacing=0 cellPadding=0
width="95%" bgColor=#f1f1f1 border=1>
<TBODY>
<TR>
<TD>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: #000000"><FONT face=新宋体><SPAN
style="COLOR: #0000ff">int</SPAN>
kmem_cache_destroy<SPAN
style="COLOR: #0000cc">(</SPAN>kmem_cache_t
<SPAN style="COLOR: #0000cc">*</SPAN>cache<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN> <BR><SPAN
style="COLOR: #ff9900">/*只在从这个缓存中分配的所有的对象都已返时才成功。因此,应检查
kmem_cache_destroy
的返回值:失败指示模块存在内存泄漏*/</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></P>
<P>使用后备高速缓存的一个好处是内核会统计后备高速缓存的使用,统计情况可从
/proc/slabinfo 获得。</P>
<P>
<HR id=null>
<FONT color=#0000ff
size=4><STRONG>内存池</STRONG></FONT>
<P></P><FONT color=#000000 size=2>
<P>为了确保在内存分配不允许失败情况下成功分配内存,内核提供了称为内存池( "mempool"
)的抽象,它其实是某种后备高速缓存。它为了紧急情况下的使用,尽力一直保持空闲内存。所以使用时必须注意:
mempool 会分配一些内存块,使其空闲而不真正使用,所以容易消耗大量内存 。而且不要使用
mempool 处理可能失败的分配。应避免在驱动代码中使用 mempool。</P>
<P>内存池的类型为 mempool_t ,在 <FONT
color=#0000ff><linux/mempool.h></FONT>
,使用方法如下:</P>
<P>(1)创建 mempool :</P></FONT></DIV>
<TABLE style="BORDER-COLLAPSE: collapse"
borderColor=#999999 cellSpacing=0 cellPadding=0
width="95%" bgColor=#f1f1f1 border=1>
<TBODY>
<TR>
<TD>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: #000000">mempool_t <SPAN
style="COLOR: #0000cc">*</SPAN>mempool_create<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000ff">int</SPAN> min_nr<SPAN
style="COLOR: #0000cc">,</SPAN></SPAN></CODE></P>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: #000000"><SPAN
style="COLOR: #0000cc">
</SPAN> mempool_alloc_t <SPAN
style="COLOR: #0000cc">*</SPAN>alloc_fn<SPAN
style="COLOR: #0000cc">,</SPAN><BR>
mempool_free_t <SPAN
style="COLOR: #0000cc">*</SPAN>free_fn<SPAN
style="COLOR: #0000cc">,</SPAN><BR>
<SPAN style="COLOR: #0000ff">void</SPAN> <SPAN
style="COLOR: #0000cc">*</SPAN>pool_data<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN> <BR><SPAN
style="COLOR: #ff9900">/*min_nr
参数是内存池应当一直保留的最小数量的分配对象*/</SPAN><BR><BR><SPAN
style="COLOR: #ff9900">/*实际的分配和释放对象由 alloc_fn 和
free_fn 处理,原型:*/</SPAN><BR><SPAN
style="COLOR: #0000ff">typedef</SPAN> <SPAN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -