- 论坛徽章:
- 0
|
本帖最后由 vonnyfly 于 2011-12-19 18:05 编辑
这些天详细看一下vmalloc的实现,打印log后发现了一个很奇怪的问题,顿时改变了我的“世界观”。
因为在log中我发现地址老不对劲,就打印PAGE_SIZE ,发现它竟然在不停的变化,呼呼~~
log 如下:地址 长度都是16进制的 PAGE_SIZE=0X1000- [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~size=1000,,PAGE_SIZE=1000,bit=13
- [ alloc_vmap_area ] vonnyfly(lfeng^-^)~~~~~~~~~~~pid=1,comm=swapper,addr=df800000,vstart=df800000,vend=fc000000,size=2000,align=2000
- /*遍历vmap_area */
- [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df800000,va_end=df802000
- [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df804000,va_end=df806000
- [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df808000,va_end=df80a000
- [ alloc_vmap_area ] vonnyfly(lfeng^-^)~~~~~~~~~~~first----va_start=df800000,va_end=df802000,addr=df800000,align=2000
- [ alloc_vmap_area ] vonnyfly(lfeng^-^)~~~~~~~~~~~first----va_start=df804000,va_end=df806000,addr=df804000,align=2000
- [ alloc_vmap_area ] vonnyfly(lfeng^-^)~~~~~~~~~~~first----va_start=df808000,va_end=df80a000,addr=df808000,align=2000
- /*遍历vmlist ,看到没 没有同步,少了一项 */
- [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist : tmp->addr=df808000,tmp->size=2000
- [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist : tmp->addr=df80c000,tmp->size=2000
- goldfish nand dev0: size 45e0000, page 2048, extra 64, erase 131072
- goldfish nand dev1: size 4000000, page 2048, extra 64, erase 131072
- goldfish nand dev2: size 4000000, page 2048, extra 64, erase 131072
复制代码 以下开始不正常了。。。。。。- [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~size=1000,,PAGE_SIZE=20000,bit=18
- [ alloc_vmap_area ] vonnyfly(lfeng^-^)~~~~~~~~~~~pid=31,comm=servicemanager,addr=df800000,vstart=df800000,vend=fc000000,size=21000,align=40000
- [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df800000,va_end=df802000
- [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df804000,va_end=df806000
- [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df808000,va_end=df80a000
- [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df80c000,va_end=df80e000
- [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df810000,va_end=df812000
- [ alloc_vmap_area ] vonnyfly(lfeng^-^)~~~~~~~~~~~first----va_start=df804000,va_end=df806000,addr=df800000,align=40000
- [ alloc_vmap_area ] vonnyfly(lfeng^-^)~~~~~~~~~~~first----va_start=df808000,va_end=df80a000,addr=df840000,align=40000
- [ alloc_vmap_area ] vonnyfly(lfeng^-^)~~~~~~~~~~~first----va_start=df80c000,va_end=df80e000,addr=df840000,align=40000
- [ alloc_vmap_area ] vonnyfly(lfeng^-^)~~~~~~~~~~~first----va_start=df810000,va_end=df812000,addr=df840000,align=40000
- [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist : tmp->addr=df808000,tmp->size=2000
- [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist : tmp->addr=df80c000,tmp->size=2000
- [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist : tmp->addr=df810000,tmp->size=2000
- [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist : tmp->addr=df840000,tmp->size=21000
- [ binder_mmap ] vonnyfly(lfeng^-^)~~~~~~~~~~~vma->vm_start=0x40009000,proc->buffer=0xdf840000
- binder: 31:31 write 4 at bec91be0, read 0 at 00000000
- binder: 31:31 wrote 4 of 4, read return 0 of 0
- binder: 31:31 write 0 at 00000000, read 128 at bec91be0
- sh: can't access tty; job control turned off
- $ eth0: link up
- warning: `rild' uses 32-bit capabilities (legacy support in use)
- binder_open: 35:59,name=rild
- [ binder_mmap ] vonnyfly(lfeng^-^)~~~~~~~~~~~binder_buffer size=40
- binder_mmap: 35 40209000-40307000 (1016 K) vma 200075 pagep 30f
- [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~size=1000,,PAGE_SIZE=fe000,bit=20
- [ alloc_vmap_area ] vonnyfly(lfeng^-^)~~~~~~~~~~~pid=59,comm=rild,addr=df800000,vstart=df800000,vend=fc000000,size=ff000,align=100000
- [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df800000,va_end=df802000
- [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df804000,va_end=df806000
- [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df808000,va_end=df80a000
- [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df80c000,va_end=df80e000
- [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df810000,va_end=df812000
- [ scanRBtree ] vonnyfly(lfeng^-^)~~~~~~~~~~~va_start=df840000,va_end=df861000
- [ alloc_vmap_area ] vonnyfly(lfeng^-^)~~~~~~~~~~~first----va_start=df804000,va_end=df806000,addr=df800000,align=100000
- [ alloc_vmap_area ] vonnyfly(lfeng^-^)~~~~~~~~~~~first----va_start=df808000,va_end=df80a000,addr=df900000,align=100000
- [ alloc_vmap_area ] vonnyfly(lfeng^-^)~~~~~~~~~~~first----va_start=df80c000,va_end=df80e000,addr=df900000,align=100000
- [ alloc_vmap_area ] vonnyfly(lfeng^-^)~~~~~~~~~~~first----va_start=df810000,va_end=df812000,addr=df900000,align=100000
- [ alloc_vmap_area ] vonnyfly(lfeng^-^)~~~~~~~~~~~first----va_start=df840000,va_end=df861000,addr=df900000,align=100000
- [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist : tmp->addr=df808000,tmp->size=2000
- [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist : tmp->addr=df80c000,tmp->size=2000
- [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist : tmp->addr=df810000,tmp->size=2000
- [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist : tmp->addr=df840000,tmp->size=21000
- [ __get_vm_area_node ] vonnyfly(lfeng^-^)~~~~~~~~~~~vmlist : tmp->addr=df900000,tmp->size=ff000
- [ binder_mmap ] vonnyfly(lfeng^-^)~~~~~~~~~~~vma->vm_start=0x40209000,proc->buffer=0xdf900000
复制代码 我是在android虚拟机上面跑得内核,采用goldfish arch,内核版本2.6.29,分配的ram=500M.添加的打印信息位置是:- static struct vm_struct *__get_vm_area_node(unsigned long size,
- unsigned long flags, unsigned long start, unsigned long end,
- int node, gfp_t gfp_mask, void *caller)
- {
- static struct vmap_area *va;
- struct vm_struct *area;
- struct vm_struct *tmp, **p;
- unsigned long align = 1;
- BUG_ON(in_interrupt());
- if (flags & VM_IOREMAP) {
- int bit = fls(size);
- if (bit > IOREMAP_MAX_ORDER)
- bit = IOREMAP_MAX_ORDER;
- else if (bit < PAGE_SHIFT)
- bit = PAGE_SHIFT;
- align = 1ul << bit;
- VONNYFLY_printk("size=%lx,,PAGE_SIZE=%lx,bit=%d",PAGE_SIZE,size,bit);//看这儿,*******PAGE_SIZE这个问题解决了,打印顺序错了,呜呜~
- }
- 。。。。。。。。。。。。
复制代码 现在说下我的疑问:
1、VM_IOREMAP这个到底干嘛的呢,仅仅是更改对齐,哪有是按照什么标准呢,int bit = fls(size);这个函数看不懂额,按照注释说的是 从右边开始不是1的那个位的位置吧,不知道理解是不是有误,1页那又为什么是13而不是12.。。。。。
2、内核vmalloc m部分搞了vmap_area vm_struct两个东西来管理,何必呢,完全可以合并阿,一个是通过RBtree来管理,一个简单的单链表。而且通过上面的log还会发现,RBtree和vmlist这两个东西有点不同步。。。是怎么回事。。
3、对alloc_vmap_area函数中间的那一陀愣是没咋看懂额。按理说一遍扫描不就ok了,怎么找了好几遍,3.0的这部分更复杂,有hole 、 cache相关的额,代码的细节好难看懂阿。- if (n) {
- struct vmap_area *first = NULL;
- do {
- struct vmap_area *tmp;
- tmp = rb_entry(n, struct vmap_area, rb_node);
- if (tmp->va_end >= addr) {
- if (!first && tmp->va_start < addr + size)
- first = tmp;
- n = n->rb_left;
- } else {
- first = tmp;
- n = n->rb_right;
- }
- } while (n);
- if (!first)
- goto found;
- if (first->va_end < addr) {
- n = rb_next(&first->rb_node);
- if (n)
- first = rb_entry(n, struct vmap_area, rb_node);
- else
- goto found;
- }
- while (addr + size > first->va_start && addr + size <= vend) {
- VONNYFLY_printk("first----va_start=%lx,va_end=%lx,addr=%lx,align=%lx",first->va_start,first->va_end,addr,align);
- addr = ALIGN(first->va_end + PAGE_SIZE, align);//xxxxxxxxxx
- if (addr + size - 1 < addr)
- goto overflow;
- n = rb_next(&first->rb_node);
- if (n)
- first = rb_entry(n, struct vmap_area, rb_node);
- else
- goto found;
- }
- }
- found:
复制代码 4、vmalloc 的实现函数 __get_vm_area_node 有点小搞不明白,这个地方插入链表的操作好奇怪,我以前一直认为指针不在话下,今儿突然发现,我越来越晕了,仔细看
- write_lock(&vmlist_lock);
- for (p = &vmlist; (tmp = *p) != NULL; p = &tmp->next) {
- if (tmp->addr >= area->addr)
- break;
- }
- area->next = *p;
- *p = area;//这一步很诡异阿,前面的东西好像没连起来额 。。。。大伙看看
复制代码 |
|