慢慢欣赏linux vmalloc vfree

vmalloc的两个数据结构也就是vm_struct和pages依赖于slab系统,pages指向的page依赖于buddy系统,另外修改页表重新映射依赖于maping

vmalloc
    =>__vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);//丫的竟然用高端内存????,是的,在最高的128M
        =>__vmalloc_node(size, gfp_mask, prot, -1);
	        =>size = PAGE_ALIGN(size); //size大小页对齐
            =>area = get_vm_area_node(size, VM_ALLOC, node, gfp_mask);//struct vm_struct *area;
                =>return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END, node, gfp_mask);//VMALLOC_START和VMALLOC_END分别是vmalloc的起始和终止区域
                    =>area = kmalloc_node(sizeof(*area), gfp_mask & GFP_LEVEL_MASK, node);//vm_struct依赖于kmalloc,也就是slab系统
	                    =>return kmalloc(size, flags);
		                    =>return kmem_cache_alloc(malloc_sizes[i].cs_cachep, flags);//进入slab领域
		            =>size += PAGE_SIZE; //We always allocate a guard page. 申请的时候加个栅栏
                    =>for (p = &vmlist; (tmp = *p) != NULL ;p = &tmp->next) { //在vmlist链表里面找到area合适的位置,把新分配的area插入到里面
                        if ((unsigned long)tmp->addr < addr) {
                            if((unsigned long)tmp->addr + tmp->size >= addr)
                                addr = ALIGN(tmp->size + 
                                         (unsigned long)tmp->addr, align);
                            continue;
                        }
                        if ((size + addr) < addr)
                            goto out;
                        if (size + addr <= (unsigned long)tmp->addr)
                            goto found;
                        addr = ALIGN(tmp->size + (unsigned long)tmp->addr, align);
                        if (addr > end - size)
                            goto out;
                    }
                    =>
                  found: //一旦找到合适的地方就初始化
                    area->next = *p;  //这两句话是将area加入到vm_struct链表中
                    *p = area;

                    area->flags = flags;
                    area->addr = (void *)addr;//addr作为内容,area作为载体
                    area->size = size;
                    area->pages = NULL;
                    area->nr_pages = 0;
                    area->phys_addr = 0;
            =>return __vmalloc_area_node(area, gfp_mask, prot, node);
	            =>nr_pages = (area->size - PAGE_SIZE) >> PAGE_SHIFT; //真正申请的时候取消栅栏,递归的时候也做递减的作用
				array_size = (nr_pages * sizeof(struct page *));
				area->nr_pages = nr_pages;
				=>if (array_size > PAGE_SIZE) {//为pages分配空间,如果pages正常占用的字节有限,但是如果超过一个页框大小,也就是4KB,需要递归调用,关于pages的详细描述详见“参考”里面的第一章节最后一张图片,很形象
					pages = __vmalloc_node(array_size, gfp_mask | __GFP_ZERO,
								PAGE_KERNEL, node);//页面大小超过1个页
					area->flags |= VM_VPAGES;
				} else {//
					pages = kmalloc_node(array_size,
							(gfp_mask & GFP_LEVEL_MASK) | __GFP_ZERO,
							node);//页面大小没有超过1个页,递归递减1个页框,最终会调用的这个地方
				}
				area->pages = pages;
				=>for (i = 0; i < area->nr_pages; i++) { 好多页面物理不连续,但是虚拟地址连续
					if (node < 0)
						area->pages[i] = alloc_page(gfp_mask);
					else
						area->pages[i] = alloc_pages_node(node, gfp_mask, 0);
					if (unlikely(!area->pages[i])) {
						/* Successfully allocated i pages, free them in __vunmap() */
						area->nr_pages = i;
						goto fail;
					}
				}
				=>if (map_vm_area(area, prot, &pages))//页表映射修改
				=>return area->addr;
void vfree(const void *addr)
	__vunmap(addr, 1);
		=>void __vunmap(const void *addr, int deallocate_pages)
			area = remove_vm_area(addr);
				=>struct vm_struct *remove_vm_area(const void *addr)
					va = find_vmap_area((unsigned long)addr);
					free_unmap_vmap_area(va);
			for (i = 0; i < area->nr_pages; i++) {
				struct page *page = area->pages[i];
				__free_page(page);
			}
			kfree(area);

参考
高端内存映射之vmalloc分配内存中不连续的页–Linux内存管理(十九)
http://blog.csdn.net/gatieme/article/details/52705111

启动过程内存check和vmalloc大小设置
https://blog.csdn.net/sunlei0625/article/details/50465713

内核中的内存申请:kmalloc、vmalloc、kzalloc、kcalloc、get_free_pages
https://www.cnblogs.com/eleclsc/p/11531589.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值