vmalloc设计的思考(?)

 

0.
   vmalloc代码倒是不难,但是就不是不太明白它的设计思想。
悲剧,到底是读代码 与 设计并写代码 差距就是很大,很难体会到设计者当初思维
过程。我们只能从给出的文档以及源代码来逆向推断设计思路,感觉本末倒置了。
有些细节及美妙灵感即使是读代码好几遍,也不如亲身去写一次考虑周全。
 
1.
就从vmalloc来说,难得在ULK中找到点ideal:
We already know that it is preferable to map memory areas into sets of contiguous page frames, thus making better use of the cache and achieving lower average memory access times. Nevertheless, if the requests for memory areas are infrequent, it makes sense to consider an allocation scheme based on noncontiguous page frames accessed through contiguous linear addresses . The main advantage of this schema is to avoid external fragmentation, while the disadvantage is that it is necessary to fiddle with the kernel Page Tables. 
 
2.
总体来说,可以臆测如下:
  +1.vmalloc是考虑减少外部碎片的(或者说是buddy system造成的内存碎片)
    它可以将连续的高端地址映射到不连续的物理页面上。
  +2.vmalloc带来的开销是,修改页表,刷新TLB,分配的内存读写较慢。好处就是1中所述。
  +3.vmalloc本身的问题,这个在当下vmalloc并不是大量使用的情况下并不会暴露,
    vmalloc基本没有使用什么高端地址空间的管理算法,简单的线性搜索空闲地址并分配出去,
    但是如果时间长了,vmalloc管理的那128MB高端地址(有时也可能不是128MB,本机测试120MB)内部就可能出现碎片
  +4.基于+1,+2,应该在分配内存不需要频繁读写的轻况下或者需求内存超过伙伴算法分配的最大页面数的情况下才启用vmalloc,但是也不尽然。
     并且vmalloc不能用于DMA!
 
3.
出于无聊,验证下vmalloc的内部碎片
(连续分配8MB/2M直到vmalloc不能分配,释放所有2MB内存,分配4MB内存,结果不能分配足够的4MB内存---这点可以从vmalloc算法里面直接看出来,这里我真的是无聊:-)
------------------------------------------------------------------
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
 
#define MAX_SIZE (130 * 1024 * 1024)
#define MB1 (1 * 1024 * 1024)
#define MB2 (2 * 1024 * 1024)
#define MB4 (4 * 1024 * 1024)
#define MB8 (8 * 1024 * 1024)
 
void *p_8M[128];
void *p_2M[128];
void *p_4M[128];
void *p_1M[128];
 
static int __init hello_init(void)
{
        unsigned int size, total_min;
        int i8, i2, i4, i1;
        void *p;
        
        total_min = 0;
        printk(KERN_ALERT "-----------vmalloc max MB---------/n");
        for (size = MAX_SIZE; size; size -= MB1) {
                p = vmalloc(size);
                if (p) {
                        total_min += size;
                        break;
                }
                
        }
        for (i1 = 0; i1 < 128; i1++) {
                if ((p_1M[i1] = vmalloc(MB1)) == NULL) {
                        i1--;
                        break;
                }
                total_min += MB1;
        }
        if (p) 
        vfree(p);
        
        for (; i1 >= 0; i1--) {
                vfree(p_1M[i1]);
        }
        printk(KERN_ALERT "total_min: %ubytes = %dMB/n",
        total_min, total_min/MB1);
        
        printk(KERN_ALERT "-----------vmalloc 8MB/2MB---------/n");
        for (i8 = i2 = 0; i2 < 128; i2++, i8++) {
                if ((p_8M[i8] = vmalloc(MB8)) == NULL) {
                        i8--;
                        i2--;
                        break;
                }
                
                total_min -= MB8;
                if ((p_2M[i2] = vmalloc(MB2)) == NULL) {
                        i2--;
                        break;
                }
                total_min -= MB2;
        }
        
        printk(KERN_ALERT "vmalloc: MB8*%d, MB2*%d/n", i8+1, i2+1);
        printk(KERN_ALERT "total_min: %ubytes = %dMB/n",
        total_min, total_min/MB1);
        printk(KERN_ALERT "-----------vfree all MB2-------------/n");
        for (; i2 >= 0; i2--) {
                vfree(p_2M[i2]);
                total_min += MB2;
        }
        printk(KERN_ALERT "total_min: %ubytes = %dMB/n",
        total_min, total_min/MB1);
        printk(KERN_ALERT "-------------vmalloc MB4---------------/n");
        for (i4 = 0; i4 < 128; i4++) {
                if ((p_4M[i4] = vmalloc(MB4)) == NULL) {
                        i4--;
                        break;
                }
                total_min -= MB4;
        }
        
        if (i4+1 == 0)
        printk(KERN_ALERT "cannot vmalloc MB4/n");
        else
        printk(KERN_ALERT "vmalloc: MB4*%d/n", i4+1);
        
        printk(KERN_ALERT "total_min: %ubytes = %dMB/n",
        total_min, total_min/MB1);
        printk(KERN_ALERT "------------vfree all-------------/n");
        for (; i8 >= 0; i8--) {
                vfree(p_8M[i8]);
                total_min += MB8;
        }
        for (; i4 >= 0; i4--) {
                vfree(p_4M[i4]);
                total_min += MB4;
        }
        printk(KERN_ALERT "total_min: %ubytes = %dMB/n",
        total_min, total_min/MB1);
        
        return 0;
}
 
static void __exit hello_exit(void)
{
        printk(KERN_ALERT "Goodbye kernel/n");
}
 
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
--------------------------------------------------------------
#insmod vm_infragement.ko
-----------vmalloc max MB---------
total_min: 121634816bytes = 116MB
-----------vmalloc 8MB/2MB---------
vmalloc: MB8*11, MB2*11
total_min: 6291456bytes = 6MB
-----------vfree all MB2-------------
total_min: 29360128bytes = 28MB
-------------vmalloc MB4---------------
vmalloc: MB4*1
total_min: 25165824bytes = 24MB                  //内存碎片
------------vfree all-------------
total_min: 121634816bytes = 116MB
 
4.JUST FOR FUN!!! (代码读过,雁过留痕= =||)
  想写个基于vmalloc的碎片整理LKM,但是不知道怎么做,因为vmalloc分配出去的地址(返回值)是不能变更的!
  恩!还在想.......

 

 

你可能感兴趣的:(算法,schema,Module,Scheme,null,Allocation)