免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1705 | 回复: 0
打印 上一主题 下一主题

vmalloc细节实现的一些疑惑 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-20 12:30 |只看该作者 |倒序浏览
本帖最后由 vonnyfly 于 2011-12-20 15:55 编辑

我是在android虚拟机上面跑得内核,采用goldfish arch,内核版本2.6.29,分配的ram=500M.添加的打印信息位置是:
  1. static struct vm_struct *__get_vm_area_node(unsigned long size,
  2.                 unsigned long flags, unsigned long start, unsigned long end,
  3.                 int node, gfp_t gfp_mask, void *caller)
  4. {
  5.         static struct vmap_area *va;
  6.         struct vm_struct *area;
  7.         struct vm_struct *tmp, **p;
  8.         unsigned long align = 1;

  9.         BUG_ON(in_interrupt());
  10.         if (flags & VM_IOREMAP) {
  11.                 int bit = fls(size);

  12.                 if (bit > IOREMAP_MAX_ORDER)
  13.                         bit = IOREMAP_MAX_ORDER;
  14.                 else if (bit < PAGE_SHIFT)
  15.                         bit = PAGE_SHIFT;

  16.                 align = 1ul << bit;
  17.                 VONNYFLY_printk("size=%lx,PAGE_SIZE=%lx,bit=%d",size,PAGE_SIZE,bit);
  18.         }
  19. 。。。。。。。。。。。。
复制代码
现在说下我的疑问:
1、VM_IOREMAP这个到底干嘛的呢,仅仅是更改对齐,那又是按照什么标准呢,int bit = fls(size);这个函数看不懂额,按照注释说的是 从右边开始不是1的那个位的位置吧,不知道理解是不是有误,1页那又为什么是13而不是12.。。。。。
  1. size=1000,,PAGE_SIZE=1000,bit=13
  2. size=20000,PAGE_SIZE=1000,bit=18
复制代码
2、内核vmalloc m部分搞了vmap_area   vm_struct两个东西来管理,何必呢,完全可以合并阿,一个是通过RBtree来管理,一个简单的单链表。而且通过上面的log还会发现,RBtree和vmlist这两个东西有点不同步。。。是怎么回事。。
这些天详细看一下vmalloc的实现,打印log后发现了一个很奇怪的问题,顿时改变了我的“世界观”。
因为在log中我发现地址老不对劲,就打印PAGE_SIZE ,发现它竟然在不停的变化,呼呼~~
log 如下:地址 长度都是16进制的   PAGE_SIZE=0X1000

  1. /*遍历vmap_area */
  2. [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df800000,va_end=df802000
  3. [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df804000,va_end=df806000
  4. [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df808000,va_end=df80a000

  5. /*遍历vmlist ,看到没  没有同步,少了一项 */
  6. [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist :  tmp->addr=df808000,tmp->size=2000
  7. [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist :  tmp->addr=df80c000,tmp->size=2000



  8. /*第二次遍历*/
  9. [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df800000,va_end=df802000
  10. [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df804000,va_end=df806000
  11. [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df808000,va_end=df80a000
  12. [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df80c000,va_end=df80e000
  13. [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df810000,va_end=df812000

  14. 还是少了一项  
  15. [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist :  tmp->addr=df808000,tmp->size=2000
  16. [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist :  tmp->addr=df80c000,tmp->size=2000
  17. [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist :  tmp->addr=df810000,tmp->size=2000
  18. [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist :  tmp->addr=df840000,tmp->size=21000


  19. 第三次
  20. [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df800000,va_end=df802000
  21. [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df804000,va_end=df806000
  22. [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df808000,va_end=df80a000
  23. [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df80c000,va_end=df80e000
  24. [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df810000,va_end=df812000
  25. [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df840000,va_end=df861000

  26. 同样不同步
  27. [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist :  tmp->addr=df808000,tmp->size=2000
  28. [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist :  tmp->addr=df80c000,tmp->size=2000
  29. [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist :  tmp->addr=df810000,tmp->size=2000
  30. [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist :  tmp->addr=df840000,tmp->size=21000
  31. [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist :  tmp->addr=df900000,tmp->size=ff000
  32. [ binder_mmap ] vonnyfly(lfeng^-^)~~~~~~~~~~~vma->vm_start=0x40209000,proc->buffer=0xdf900000
复制代码
3、对alloc_vmap_area函数中间的那一陀愣是没咋看懂额。按理说一遍扫描不就ok了,怎么找了好几遍,3.0的这部分更复杂,有hole 、 cache相关的额,代码的细节好难看懂阿。
  1. if (n) {
  2.                 struct vmap_area *first = NULL;

  3.                 do {
  4.                         struct vmap_area *tmp;
  5.                         tmp = rb_entry(n, struct vmap_area, rb_node);
  6.                         if (tmp->va_end >= addr) {
  7.                                 if (!first && tmp->va_start < addr + size)
  8.                                         first = tmp;//first这个地方干嘛的,反正vm区又不能重叠,检查是否过多呢
  9.                                 n = n->rb_left;
  10.                         } else {
  11.                                 first = tmp;
  12.                                 n = n->rb_right;
  13.                         }
  14.                 } while (n);

  15.                 if (!first)//first为空,就found?
  16.                         goto found;

  17.                 if (first->va_end < addr) {
  18.                         n = rb_next(&first->rb_node);
  19.                         if (n)
  20.                                 first = rb_entry(n, struct vmap_area, rb_node);
  21.                         else
  22.                                 goto found;
  23.                 }

  24.                 while (addr + size > first->va_start && addr + size <= vend) {
  25.                         VONNYFLY_printk("first----va_start=%lx,va_end=%lx,addr=%lx,align=%lx",first->va_start,first->va_end,addr,align);
  26.                         addr = ALIGN(first->va_end + PAGE_SIZE, align);//xxxxxxxxxx
  27.                         if (addr + size - 1 < addr)
  28.                                 goto overflow;

  29.                         n = rb_next(&first->rb_node);
  30.                         if (n)
  31.                                 first = rb_entry(n, struct vmap_area, rb_node);
  32.                         else
  33.                                 goto found;
  34.                 }
  35.         }
  36. found:
复制代码
4、vmalloc 的实现函数  __get_vm_area_node  有点小搞不明白,这个地方插入链表的操作好奇怪,我以前一直认为指针不在话下,今儿突然发现,我越来越晕了,仔细看

  1.         write_lock(&vmlist_lock);
  2.         for (p = &vmlist; (tmp = *p) != NULL; p = &tmp->next) {
  3.                 if (tmp->addr >= area->addr)
  4.                         break;
  5.         }  
  6.         area->next = *p;//*p此时指向下一个位置
  7.         *p = area;//这一步很诡异阿,前面的东西好像没连起来额  。。。。大伙看看
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP