linux内存管理之非连续物理地址分配(vmalloc)
)
addr = ALIGN(tmp->size (unsigned long)tmp->addr, align); continue; } //size addr < addr ?除非size == 0 if ((size addr) < addr) goto out; //中间的空隙可以容纳下size大小的vm.说明已经找到了这样的一个vm if (size addr <= (unsigned long)tmp->addr) goto found; //调整起始地址为vm的结束地址 addr = ALIGN(tmp->size (unsigned long)tmp->addr, align); //如果超出了范围 if (addr > end - size) goto out; } found: //找到了合适大小的空间,将area->addr赋值为addr,然后链入vmlist中 area->next = *p; *p = area; area->flags = flags; 拥有帝国一切,皆有可能。欢迎访问phome.net area->addr = (void *)addr; area->size = size; area->pages = NULL; area->nr_pages = 0; area->phys_addr = 0; write_unlock(&vmlist_lock); return area; out: //没有找到合适大小的空间,出错返回 write_unlock(&vmlist_lock); kfree(area); if (printk_ratelimit()) printk(KERN_WARNING "allocation failed: out of vmalloc space - use vmalloc=<size> to increase size.n"); return NULL; }
这段代码不是很复杂,在此不详细分析了. remove_vm_area用来将相应的vm从vmlist中断开,使其表示的空间可以被利用 //addr:对应vm的超始地址 struct vm_struct *remove_vm_area(void *addr) { struct vm_struct **p, *tmp; write_lock(&vmlist_lock); //遍历vmlist.找到超始地址为addr的vm for (p = &vmlist ; (tmp = *p) != NULL ;p = &tmp->next) { if (tmp->addr == addr) goto found; } write_unlock(&vmlist_lock); return NULL; found: //断开tmp所对应的映射关系 unmap_vm_area(tmp); //找到了这个vm,将其从vmlist上断开 *p = tmp->next; write_unlock(&vmlist_lock); return tmp; } unmap_vm_area用来断开vm所在线性地址所对应的映射关系.它的代码如下: void unmap_vm_area(struct vm_struct *area) { //vm所对应的起始线性地址 unsigned long address = (unsigned long) area->addr; //vm所对应的结束线性地址 unsigned long end = (address area->size); pgd_t *dir; //起始地址所在的内核页目录项 dir = pgd_offset_k(address); flush_cache_vunmap(address, end); do { //断开地址所对应的pmd映射 unmap_area_pmd(dir, address, end - address); //运行到这里的时候,已经断开了一个页目录所表示的线性地址,而每个页目录表示的线性地址//大小为PGDIR_SIZE 拥有帝国一切,皆有可能。欢迎访问phome.net address = (address PGDIR_SIZE) & PGDIR_MASK; dir ; } while (address && (address < end)); //当到达末尾时结束循环 flush_tlb_kernel_range((unsigned long) area->addr, end); } //断开线性地址区间所在的pmd的映射 static void unmap_area_pmd(pgd_t *dir, unsigned long address, unsigned long size) { unsigned long end; pmd_t *pmd; if (pgd_none(*dir)) return; if (pgd_bad(*dir)) {
|
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |