linux内存管理之非连续物理地址分配(vmalloc)
pgd_ERROR(*dir);
pgd_clear(dir); return; } pmd = pmd_offset(dir, address); address &= ~PGDIR_MASK; end = address size; if (end > PGDIR_SIZE) end = PGDIR_SIZE; do { //断开线性地址所在的pte的映射关系 unmap_area_pte(pmd, address, end - address); address = (address PMD_SIZE) & PMD_MASK; pmd ; } while (address < end); } static void unmap_area_pte(pmd_t *pmd, unsigned long address, unsigned long size) { unsigned long end; pte_t *pte; if (pmd_none(*pmd)) return; if (pmd_bad(*pmd)) { pmd_ERROR(*pmd); pmd_clear(pmd); return; } pte = pte_offset_kernel(pmd, address); address &= ~PMD_MASK; end = address size; if (end > PMD_SIZE) end = PMD_SIZE; do { pte_t page; //清除pte的对应映射关系 page = ptep_get_and_clear(pte); address = PAGE_SIZE; pte ; if (pte_none(page)) continue; if (pte_present(page)) continue; printk(KERN_CRIT "Whee.. Swapped out page in kernel page tablen"); } while (address < end); } 经过这几个过程之后,实际上,它只是找到线性地址所对应的pte,然后断开pte的映射.值得注意的是:为了效率起见,这里只是断开了pte的映射,即只是将pte置为none,表示pte末映射内存.并末断开pmd和pgd的映射 拥有帝国一切,皆有可能。欢迎访问phome.net
三:vmalloc的实现: void *vmalloc(unsigned long size) { return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL); } 实际上调用__vmalloc: void *__vmalloc(unsigned long size, int gfp_mask, pgprot_t prot) { struct vm_struct *area; struct page **pages; unsigned int nr_pages, array_size, i; //使请求的大小与页框对齐 size = PAGE_ALIGN(size); //有效性检查 if (!size || (size >> PAGE_SHIFT) > num_physpages) return NULL; //取得一个有效的VM,这个函数我们在前面已经详细的分析过了 area = get_vm_area(size, VM_ALLOC); if (!area) return NULL; //所要映射的页面总数 nr_pages = size >> PAGE_SHIFT; //页面描述符所占的空间 array_size = (nr_pages * sizeof(struct page *)); area->nr_pages = nr_pages; area->pages = pages = kmalloc(array_size, (gfp_mask & ~__GFP_HIGHMEM)); //如果空间分配失败 if (!area->pages) { remove_vm_area(area->addr); kfree(area); return NULL; } memset(area->pages, 0, array_size); //为每一个页面分配空间 for (i = 0; i < area->nr_pages; i ) { area->pages[i] = alloc_page(gfp_mask); if (unlikely(!area->pages[i])) { /* Successfully allocated i pages, free them in __vunmap() */ area->nr_pages = i; goto fail; } } //为所分配的页面建立映射关系 if (map_vm_area(area, prot, &pages)) goto fail; return area->addr; fail: vfree(area->addr); return NULL; } map_vm_area为所分配的内存建立映射关系 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |