标签:
转自:http://blog.csdn.net/myarrow/article/details/7208777
1. 内存分配函数
相关代码如下:
#define alloc_pages(gfp_mask, order) alloc_pages_node(numa_node_id(), gfp_mask, order)
#define alloc_page_vma(gfp_mask, vma, addr) alloc_pages(gfp_mask, 0)
#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
#define __get_free_page(gfp_mask) __get_free_pages((gfp_mask),0)
#define __get_dma_pages(gfp_mask, order) __get_free_pages((gfp_mask) | GFP_DMA,(order))
#define pfn_to_page(pfn) (mem_map + ((pfn) - PHYS_PFN_OFFSET))
#define page_to_pfn(page) ((unsigned long)((page) - mem_map) + PHYS_PFN_OFFSET)
#define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
#define phys_to_page(phys) (pfn_to_page(phys >> PAGE_SHIFT))
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
1)__get_free_pages实现代码如下,它返回页的虚拟地址:
- unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
- {
- struct page *page;
-
-
- VM_BUG_ON((gfp_mask & __GFP_HIGHMEM) != 0);
-
- page = alloc_pages(gfp_mask, order);
- if (!page)
- return 0;
- return (unsigned long) page_address(page);
- }
- void *page_address(struct page *page)
- {
- unsigned long flags;
- void *ret;
- struct page_address_slot *pas;
-
- if (!PageHighMem(page))
- return lowmem_page_address(page);
-
- pas = page_slot(page);
- ret = NULL;
- spin_lock_irqsave(&pas->lock, flags);
- if (!list_empty(&pas->lh)) {
- struct page_address_map *pam;
-
- list_for_each_entry(pam, &pas->lh, list) {
- if (pam->page == page) {
- ret = pam->virtual;
- goto done;
- }
- }
- }
- done:
- spin_unlock_irqrestore(&pas->lock, flags);
- return ret;
- }
- static __always_inline void *lowmem_page_address(struct page *page)
- {
- return __va(PFN_PHYS(page_to_pfn(page)));
- }
2)alloc_pages_node
- static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask,
- unsigned int order)
- {
-
- if (nid < 0)
- nid = numa_node_id();
-
- return __alloc_pages(gfp_mask, order, node_zonelist(nid, gfp_mask));
- }
参数nid是要分配内存的 NUMA节点 ID,
参数gfp_mask是 GFP_分配标志,
参数order是分配内存的大小(2^order个页面).
返回值是一个指向第一个(可能返回多个页)page结构的指针,失败时返回NULL。
- static inline struct page *
- __alloc_pages(gfp_t gfp_mask, unsigned int order,
- struct zonelist *zonelist)
- {
- return __alloc_pages_nodemask(gfp_mask, order, zonelist, NULL);
- }
- struct page *
- __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
- struct zonelist *zonelist, nodemask_t *nodemask)
- {
- enum zone_type high_zoneidx = gfp_zone(gfp_mask);
- struct zone *preferred_zone;
- struct page *page;
- int migratetype = allocflags_to_migratetype(gfp_mask);
-
- gfp_mask &= gfp_allowed_mask;
-
- lockdep_trace_alloc(gfp_mask);
-
- might_sleep_if(gfp_mask & __GFP_WAIT);
-
- if (should_fail_alloc_page(gfp_mask, order))
- return NULL;
-
-
- if (unlikely(!zonelist->_zonerefs->zone))
- return NULL;
-
- get_mems_allowed();
-
- first_zones_zonelist(zonelist, high_zoneidx,
- nodemask ? : &cpuset_current_mems_allowed,
- &preferred_zone);
- if (!preferred_zone) {
- put_mems_allowed();
- return NULL;
- }
-
-
- page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, order,
- zonelist, high_zoneidx, ALLOC_WMARK_LOW|ALLOC_CPUSET,
- preferred_zone, migratetype);
- if (unlikely(!page))
- page = __alloc_pages_slowpath(gfp_mask, order,
- zonelist, high_zoneidx, nodemask,
- preferred_zone, migratetype);
- put_mems_allowed();
-
- trace_mm_page_alloc(page, order, gfp_mask, migratetype);
- return page;
- }
其接下来的主要调用流程如下:
get_page_from_freelist->
buffered_rmqueue
3) buffered_rmqueue
从区域zone中获取一块大小为2^order的物理内存块,返回该内存块的首个页框的描述符page。
- static inline
- struct page *buffered_rmqueue(struct zone *preferred_zone,
- struct zone *zone, int order, gfp_t gfp_flags,
- int migratetype)
- {
- unsigned long flags;
- struct page *page;
- int cold = !!(gfp_flags & __GFP_COLD);
-
- again:
- if (likely(order == 0)) {
- struct per_cpu_pages *pcp;
- struct list_head *list;
-
- local_irq_save(flags);
- pcp = &this_cpu_ptr(zone->pageset)->pcp;
- list = &pcp->lists[migratetype];
- if (list_empty(list)) {
- pcp->count += rmqueue_bulk(zone, 0,
- pcp->batch, list,
- migratetype, cold);
- if (unlikely(list_empty(list)))
- goto failed;
- }
-
- if (cold)
- page = list_entry(list->prev, struct page, lru);
- else
- page = list_entry(list->next, struct page, lru);
-
- list_del(&page->lru);
- pcp->count--;
- } else {
- if (unlikely(gfp_flags & __GFP_NOFAIL)) {
-
- WARN_ON_ONCE(order > 1);
- }
- spin_lock_irqsave(&zone->lock, flags);
- page = __rmqueue(zone, order, migratetype);
- spin_unlock(&zone->lock);
- if (!page)
- goto failed;
- __mod_zone_page_state(zone, NR_FREE_PAGES, -(1 << order));
- }
-
- __count_zone_vm_events(PGALLOC, zone, 1 << order);
- zone_statistics(preferred_zone, zone, gfp_flags);
- local_irq_restore(flags);
-
- VM_BUG_ON(bad_range(zone, page));
- if (prep_new_page(page, order, gfp_flags))
- goto again;
- return page;
-
- failed:
- local_irq_restore(flags);
- return NULL;
- }
4) rmqueue_bulk
用于多次(count)内存申请.
- static int rmqueue_bulk(struct zone *zone, unsigned int order,
- unsigned long count, struct list_head *list,
- int migratetype, int cold)
- {
- int i;
-
- spin_lock(&zone->lock);
- for (i = 0; i < count; ++i) {
- struct page *page = __rmqueue(zone, order, migratetype);
- if (unlikely(page == NULL))
- break;
-
-
- if (likely(cold == 0))
- list_add(&page->lru, list);
- else
- list_add_tail(&page->lru, list);
- set_page_private(page, migratetype);
- list = &page->lru;
- }
- __mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order));
- spin_unlock(&zone->lock);
- return i;
- }
5) __rmqueue
用于一次内存申请。
- static struct page *__rmqueue(struct zone *zone, unsigned int order,
- int migratetype)
- {
- struct page *page;
-
- retry_reserve:
- page = __rmqueue_smallest(zone, order, migratetype);
-
- if (unlikely(!page) && migratetype != MIGRATE_RESERVE) {
- page = __rmqueue_fallback(zone, order, migratetype);
-
-
- if (!page) {
- migratetype = MIGRATE_RESERVE;
- goto retry_reserve;
- }
- }
-
- trace_mm_page_alloc_zone_locked(page, order, migratetype);
- return page;
- }
2. 内存释放函数
相关宏定义如下:
- #define __free_page(page) __free_pages((page), 0)
- #define free_page(addr) free_pages((addr),0)
Kernel 3.0.8 内存管理函数【转】
标签:
原文地址:http://www.cnblogs.com/sky-heaven/p/4837257.html