高端内存相关?
Pages
//内核把物理页面当做内存管理的基本单元
The kernel represents every physical page on the system with a struct page structure. This structure is defined in <linux/mm.h>:
//内核用struct page 结构体 代表每个物理页面
struct page {
page_flags_t flags;
atomic_t _count;
atomic_t _mapcount;
unsigned long private;
struct address_space *mapping;
pgoff_t index;
struct list_head lru;
void *virtual;
};
主要域的解析:
FLAGS:
The flags field stores the status of the page. Such flags include whether the page is dirty or whether it is locked in memory. Bit flags represent the various values, so at least 32 different flags are simultaneously available. The flag values are defined in <linux/page-flags.h>.
_COUNT:
The _count field stores the usage count of the pagethat is, how many references there are to this page.
VIRTUAL:
The virtual field is the page's virtual address. Normally, this is simply the address of the page in virtual memory. Some memory (called high memory) is not permanently mapped in the kernel's address space. In that case, this field is NULL and the page must be dynamically mapped when needed
Zones
Because of hardware limitations, the kernel cannot treat all pages as identical. Some pages, because of their physical address in memory, cannot be used for certain tasks. Because of this limitation, the kernel divides pages into different zones. The kernel uses the zones to group pages of similar properties.
there are three memory zones in Linux:
ZONE_DMA This zone contains pages that are capable of undergoing DMA.
ZONE_NORMAL This zone contains normal, regularly mapped, pages.
ZONE_HIGHMEM This zone contains "high memory," which are pages not permanently mapped into the kernel's address space.
These zones are defined in <linux/mmzone.h>.
一些分配内存的函数!!!
在下面的函数中 :
page structure 即返回的是直接指向物理内存中的内存空间的指针
logical address 即返回的是指向虚拟内存空间的内存的指针
注意!:
This function works the same as alloc_pages(), except that it directly returns the logical address of the first requested page. Because the pages are contiguous, the other pages simply follow from the first.
分配与释放内存空间!!!
unsigned long page;
page = __get_free_pages(GFP_KERNEL, 3);
if (!page) {
/* insufficient memory: you must handle this error! */
return ENOMEM;
}
/* 'page' is now the address of the first of eight contiguous pages ... */
free_pages(page, 3);
/*
* our pages are now freed and we should no
* longer access the address stored in 'page'
*/
The function is declared in <linux/slab.h>:
void * kmalloc(size_t size, int flags)
参数FLAG的使用!!!!
GFP_KERNEL 可能会引起阻塞,使reached!所以不能用在..........
GFP_AROMIC就解决了这个问题
.
char *buf;
buf = kmalloc(BUF_SIZE, GFP_ATOMIC);
if (!buf)
/* error allocting memory ! */
Later, when you no longer need the memory, do not forget to free it:
kfree(buf);
VMALLOC()
The kmalloc() function guarantees that the pages are physically
contiguous (and virtually contiguous).
The vmalloc() function only ensures that the pages are contiguous within
the virtual address space.
一般硬件要求的则是连续的物理地址!!!!
For the most part, only hardware devices require physically
contiguous memory allocations.
/**********************************************************
下面的红字是TLB的解释:
The TLB (translation lookaside buffer) is a hardware cache used by
most architectures to cache the mapping of virtual addresses to physical
addresses. This greatly improves the performance of the system,
because most memory access is done via virtual addressing.
一般在内核代码中,都是使用
kmalloc申请的内存空间物理地址和虚拟地址都是连续的!
vmalloc申请的内存空间虚拟地址连续,而物理地址不是连续的!
必须建立一个页表的入口(page table entries),而且,物理内存需要一页一页的(因为不是连续的!)映射到虚拟内存空间。这样与一整块物理内存直接映射相比,TLB要做多的多的工作。所以vmalloc()函数开销大 ,所以,它一般用做于申请一大块的内存空间!
kmalloc() ,因为使用vmalloc() 的开销比它大。 为了使物理内存中不连续的页在虚拟内存中是连续的,于上面文字对应的英语正文如下:
most kernel code uses kmalloc() and not vmalloc()
to obtain memory. Primarily, this is for performance.
The vmalloc() function, to make nonphysically contiguous
pages contiguous in the virtual address space, must specifically set up
the page table entries. Worse, pages obtained via vmalloc() must be mapped by
their individual pages (because they are not physically contiguous),
which results in much greater TLB[4] thrashing than you see when directly
mapped memory is used. Because of these concerns, vmalloc() is used only
when absolutely necessary typically, to obtain very large regions of memory.
For example, when modules are dynamically inserted into the kernel,
they are loaded into memory created via vmalloc().
一个运用vmalloc函数的例子: 当动态插入驱动模块时!!!!!!!!!
使用例子:
char *buf;
buf = vmalloc(16 * PAGE_SIZE); /* get 16 pages */
if (!buf)
/* error! failed to allocate memory */
/*
* buf now points to at least a 16*PAGE_SIZE bytes
* of virtually contiguous block of memory
*/
After you are finished with the memory, make sure to free it by using
vfree(buf);