📄 kernel_space_memory_allocation.html
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head> <title></title> <link rel="stylesheet" media="screen" type="text/css" href="./style.css" /> <link rel="stylesheet" media="screen" type="text/css" href="./design.css" /> <link rel="stylesheet" media="print" type="text/css" href="./print.css" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><a href=start.html>start</a></br><div class="toc"><div class="tocheader toctoggle" id="toc__header">Table of Contents</div><div id="toc__inside"><ul class="toc"><li class="clear"><ul class="toc"><li class="level2"><div class="li"><span class="li"><a href="#memory_in_the_kernel" class="toc">Memory in the Kernel</a></span></div><ul class="toc"><li class="level3"><div class="li"><span class="li"><a href="#kmalloc" class="toc">Kmalloc</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#get_free_page_s" class="toc">Get_Free_Page(s)</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#vmalloc" class="toc">Vmalloc</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#mmuless_systems" class="toc">MMUless Systems</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#difference_between_gfp_kernel_and_gfp_dma" class="toc">Difference between GFP_KERNEL and GFP_DMA</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#problems_in_uclinux_power_of_two_memory_allocation_defragmentation" class="toc">Problems in uClinux power of two memory allocation (defragmentation)</a></span></div></li></ul></li><li class="level2"><div class="li"><span class="li"><a href="#cache_management" class="toc">Cache Management</a></span></div><ul class="toc"><li class="level3"><div class="li"><span class="li"><a href="#instruction_cache" class="toc">Instruction Cache</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#data_cache" class="toc">Data Cache</a></span></div></li></ul></li></ul></li></ul></div></div><h2><a name="memory_in_the_kernel" id="memory_in_the_kernel">Memory in the Kernel</a></h2><div class="level2"><p> One of the Kernel’s main tasks is to allocate memory to processes and kernel functions. There are, in fact, three primary Kernel based memory allocation schemes. </p><ul><li class="level1"><div class="li"> Bootmem allocator - only used during system boot</div></li><li class="level1"><div class="li"> Buddy Allocator - gives out whole pages </div></li><li class="level1"><div class="li"> Slab Allocator - allocates smaller blocks of memory</div></li></ul></div><!-- SECTION [1-355] --><h3><a name="kmalloc" id="kmalloc">Kmalloc</a></h3><div class="level3"><p> Kmalloc is used to grab small pieces of memory in kernel space. Normally the size is limited to 128K bytes but a Kernel Configuration option </p><pre class="code">CONFIG_LARGE_ALLOCS </pre><p> that allows the size to be increased to 32M. </p><p>On MMUless systems the maximum memory allocation size is increased to 1M.</p><p> Refer to the following sources for more details </p><ul><li class="level1"><div class="li"> <strong>linux-2.6.x/mm/slab.c</strong></div></li><li class="level1"><div class="li"> <strong>linux-2.6.x/include/linux/slab.h</strong></div></li><li class="level1"><div class="li"> <strong>linux-2.6.x/include/linux/kmalloc_sizes.h<</strong></div></li></ul><p> Typical use </p><pre class="code"> // get memory char * p = kmalloc(size, flags); // free memory kfree(p); p=NULL;</pre><p>This will return <strong>NULL</strong> if the allocation failed.</p><p>The flags argument may be one of: </p><ul><li class="level1"><div class="li"> GFP_USER - Allocate memory on behalf of user. May sleep.</div></li><li class="level1"><div class="li"> GFP_KERNEL - Allocate normal kernel ram. May sleep.</div></li><li class="level1"><div class="li"> GFP_ATOMIC - Allocation will not sleep. Use inside interrupt handlers.</div></li></ul><p>Additionally, the GFP_DMA flag may be set to indicate the memory must be suitable for DMA. This can mean different things on different platforms. For example, on i386, it means that the memory must come from the first 16MB and thus be suitable for devices restricted to 24 bit addressing.</p></div><!-- SECTION [356-1546] --><h3><a name="get_free_page_s" id="get_free_page_s">Get_Free_Page(s)</a></h3><div class="level3"><p>Get_free_page(s) is used to allocate larger contiguous blocks of memory.</p><p>The min page size is 1 page 4k (4096). The “normal” increment is by powers of 2 called the “order”.</p><p>Refer to the following sources: </p><ul><li class="level1"><div class="li"> <strong>linux-2.6.x/mm/page_alloc.c</strong></div></li><li class="level1"><div class="li"> <strong>linux-2.6.x/include/linux/gfp.h</strong></div></li></ul><p>The use of the kernel call is as follows:</p><pre class="code c"> <span class="kw4">char</span> * kbuf; kbuf = <span class="br0">(</span><span class="kw4">char</span> *<span class="br0">)</span>__get_free_page<span class="br0">(</span>GFP_KERNEL<span class="br0">)</span>; <span class="kw1">if</span> <span class="br0">(</span>!kbuf<span class="br0">)</span> <span class="kw1">return</span> -ENOMEM; <span class="kw4">char</span> * resp; <span class="kw4">int</span> order; order = <span class="nu0">2</span>; <span class="co1">//( 16K page please )</span> resp = <span class="br0">(</span><span class="kw4">char</span> *<span class="br0">)</span> __get_free_pages<span class="br0">(</span>GFP_KERNEL, order<span class="br0">)</span>; <span class="kw1">if</span> <span class="br0">(</span>!resp<span class="br0">)</span> <span class="kw1">return</span> -ENOMEM; </pre><p>This system uses the buddy allocator that allocates memory pages sized by a power of 2 factor. This means that you can get 1 , 2, 4, 8, 16, 32, 64 pages ( each of 4 K bytes in size ), but nothing in between.</p><p>The memory is contiguous. If no memory can be found the call may block unless the GFP_ATOMIC flag is specified. In this case the call will return a NULL pointer to indicate failure.</p></div><!-- SECTION [1547-2715] --><h3><a name="vmalloc" id="vmalloc">Vmalloc</a></h3><div class="level3"><p> Used on MMUFull systems. This allows the mapping of buffers greater than the kmalloc limit ( Normally 128K ). Memory is mapped one page at a time and the resultant virtual memory is logically contiguous but may not be actually physically contiguous. In an MMU based system, the physical memory is mapped into a special area reserved in the 4G kernel memory map for this sort of operation.</p><p>ON MMUless systems the vmalloc function is defined in a file called linux-2.6.x/mm/nommu.c. This files is linked into the kernel instead of the MMU based files.</p><p>This extract from the Kernel Makefile shows how:</p><pre class="code">mmu-y := nommu.ommu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \ mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \ shmem.o vmalloc.o</pre></div><!-- SECTION [2716-3588] --><h3><a name="mmuless_systems" id="mmuless_systems">MMUless Systems</a></h3><div class="level3"><p>In general the transition between MMUfull and MMUless operation is restricted to a minimal number of changes in a few source files.</p><pre class="code"> For interest see these files for more instances using the CONFIG_MMU configuration option. ./drivers/char/mem.c ./drivers/ieee1394/dma.c ./drivers/video/fbmem.c ./fs/compat.c ./fs/exec.c ./kernel/fork.c ./mm/filemap.c ./mm/nommu.c ./mm/page_alloc.c ./mm/slab.c ./include/linux/blkdev.h ./include/linux/kmalloc_sizes.h ./include/linux/rmap.h ./include/linux/swap.h</pre></div><!-- SECTION [3589-4245] --><h3><a name="difference_between_gfp_kernel_and_gfp_dma" id="difference_between_gfp_kernel_and_gfp_dma">Difference between GFP_KERNEL and GFP_DMA</a></h3><div class="level3"><p> On most architectures GFP_DMA is an extension to the GFP_KERNEL flag to request memory to be allocated from the first 16M of physical memory. This was ( or still is a restriction on some hardware with only 24 bit addressing abilities.</p><p>Other architectures can use the GFP_DMA flag to allocate memory best suited for DMA activities.</p></div><!-- SECTION [4246-4632] --><h3><a name="problems_in_uclinux_power_of_two_memory_allocation_defragmentation" id="problems_in_uclinux_power_of_two_memory_allocation_defragmentation">Problems in uClinux power of two memory allocation (defragmentation)</a></h3><div class="level3"><p> The buddy allocator provides memory in packets of increasing order of 2 size. This provides for a fast efficient allocator on system with larger memories ( Desktop Systems ).</p><p>On really small Embedded Systems with only a few M bytes of memory the buffy allocator can quickly use up the available memory. This can cause the system to fail due to lack of memory prematurely.</p><p>The Buddy Allocator was optionally replaced on the 2.4 Kernels by the “Non Power of 2” allocator. This was slower than the Buddy Allocator but did not have the same memory size restraints as the buddy allocator. This means that system that seemed to run out of memory using the buddy allocator would work using the “Non Power of 2” allocator.</p><p>This memory allocator has not (yet ) been ported to the 2.6 kernel.</p></div><!-- SECTION [4633-5503] --><h2><a name="cache_management" id="cache_management">Cache Management</a></h2><div class="level2"><p>A portion of the L1 internal memory can be configured as data and instruction caches. For the BF533 the following Memory Map is available </p><table class="inline"> <tr> <td> Type of Memory </td><td> Size </td> </tr> <tr> <td> Instruction SRAM or Cache </td><td> 16K byte </td> </tr> <tr> <td class="leftalign"> Instruction SRAM </td><td> 64K byte </td> </tr> <tr> <td> Data SRAM or Cache </td><td> 32K byte </td> </tr> <tr> <td class="leftalign"> Data SRAM </td><td> 32K byte </td> </tr> <tr> <td> Scratchpad SRAM </td><td> 4K byte </td> </tr></table><br /></div><!-- SECTION [5504-5865] --><h3><a name="instruction_cache" id="instruction_cache">Instruction Cache</a></h3><div class="level3"><p>The IMEM_CONTROL register is used to set up the mode of the Instruction SRAM as either a cache or additional instruction storage. Write access to this area is only via a DMA port because the memory is effectively 64 bits wide. The Instruction cache needs to be managed manually if the physical memory referenced may have changed. Instructions are available to invlaidate a single cache line , an addres or the complete cache.</p><p>Code is in the file <strong>linux-2.6.x/arch/blackfin/mach-common/flush.S</strong> to manage flusing both Instructions and Data Caches.</p></div><!-- SECTION [5866-6447] --><h3><a name="data_cache" id="data_cache">Data Cache</a></h3><div class="level3"><p> The system has an optional 32K byte Data Cache</p><p>This can be configured ( in the kernel Configuration System ) in many ways </p><ul><li class="level1"><div class="li"> CONFIG_BLKFIN_CACHE - Instruction Cache</div></li><li class="level1"><div class="li"> CONFIG_BLKFIN_DCACHE - Data Cache</div></li><li class="level1"><div class="li"> CONFIG_BLKFIN_CACHE_LOCK - provides code to lock the cache </div></li><li class="level1"><div class="li"> CONFIG_BLKFIN_WB - Write Back Cache</div></li><li class="level1"><div class="li"> CONFIG_BLKFIN_WT - Write Through Cache</div></li><li class="level1"><div class="li"> CONFIG_UNCACHED_1MB - leave 1Mbyte at top of memory untouched by Linux</div></li></ul><p> The following Data Cache types are available </p><ul><li class="level1"><div class="li"> Write Through - each store in goes to memory and cache</div></li><li class="level1"><div class="li"> Write Back - Actual memory is updated only if the cache line is replaced.</div></li><li class="level1"><div class="li"> A SSYNC instruction will flush the cache write buffer</div></li></ul><p>As with the instruction cache care must be taken to flush or invalidate the cache whenever some external system may have changed the physical memory dorectly. </p></div><!-- SECTION [6448-] --></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -