内存区操作函数分析
1431 /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ 1432 struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr) 1433 { 1434 struct vm_area_struct *vma = NULL; 1435 1436 if (mm) { 1437 /* Check the cache first. */ 1438 /* (Cache hit rate is typically around 35%.) */ 1439 vma = mm->mmap_cache; 1440 if (!(vma && vma->vm_end > addr && vma->vm_start <= addr)) { 1441 struct rb_node * rb_node; 1442 1443 rb_node = mm->mm_rb.rb_node; 1444 vma = NULL; 1445 1446 while (rb_node) { 1447 struct vm_area_struct * vma_tmp; 1448 1449 vma_tmp = rb_entry(rb_node, 1450 struct vm_area_struct, vm_rb); 1451 1452 if (vma_tmp->vm_end > addr) { 1453 vma = vma_tmp; 1454 if (vma_tmp->vm_start <= addr) 1455 break; 1456 rb_node = rb_node->rb_left; 1457 } else 1458 rb_node = rb_node->rb_right; 1459 } 1460 if (vma) 1461 mm->mmap_cache = vma; 1462 } 1463 } 1464 return vma; 1465 }
find_vma用来在内存区查找第一个结束地址在addr之后的vma,
1439 根据局部性原理,内核首先检查上次处理的区域是否包含本次所需的地址,即mmap_cache包含住这个地址,如果成立,那么直接从1464返回。
1441~1463 不包含在mmap_cache中,那么我们从红黑树的根节点开始,进行查找.
1446 ~ 1459 红黑树的查找很简单,如果节点的结束地址大于addr并且开始地址小于addr,那么说明已经找到,退出循环;否则在进入不同的树分支。
1460~1461 用找到的vma更新mmap_cache
1073 /* Look up the first VMA which intersects the interval start_addr..end_addr-1, 1074 NULL if none. Assume start_addr < end_addr. */ 1075 static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * mm, unsigned long start_addr, unsigned long end_addr) 1076 { 1077 struct vm_area_struct * vma = find_vma(mm,start_addr); 1078 1079 if (vma && end_addr <= vma->vm_start) 1080 vma = NULL; 1081 return vma; 1082 }
1407 unsigned long 1408 get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, 1409 unsigned long pgoff, unsigned long flags) 1410 { 1411 unsigned long (*get_area)(struct file *, unsigned long, 1412 unsigned long, unsigned long, unsigned long); 1413 1414 get_area = current->mm->get_unmapped_area; 1415 if (file && file->f_op && file->f_op->get_unmapped_area) 1416 get_area = file->f_op->get_unmapped_area; 1417 addr = get_area(file, addr, len, pgoff, flags); 1418 if (IS_ERR_VALUE(addr)) 1419 return addr; 1420 1421 if (addr > TASK_SIZE - len) 1422 return -ENOMEM; 1423 if (addr & ~PAGE_MASK) 1424 return -EINVAL; 1425 1426 return addr; 1427 }