进程地址空间 - 辅助函数分析

内存区操作函数分析


find_vmd

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


find_vma_intersection

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 }    

这个函数的作用是找到一个VMA,使得这个vma完全包含start_addr和end_addr定义的空间。


get_unmapped_area

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 } 



你可能感兴趣的:(进程地址空间 - 辅助函数分析)