PMON中的虚拟内存问题

PMON中的虚拟内存问题

分类: Loongson Pmon 15人阅读 评论(0) 收藏 举报

 

net_init函数中通过vminit和kmeminit函数来完成虚拟内存映射以及内存分配的初始化,暂时先将看的笔记放上来,以后整理:

#define PGOFSET 4095 

 

size = (size + PGOFSET)& ~PGOFSET  // 0x0fff

 

该语句的作用在于:

每次分配都按PGOFSET为单位进行分配,size不足PGOFSET的则分配PGOFSET大小,size大于PGOFSET的则分配

(size / PGOFSET+1)*PGOFSET 大小;

 

假设size = PGOFSET + 1,那么分配时将会分配2*PGOFSET大小;

 

 

 

 

  1. 1.virtua memory init(在sys/kern/kern_misc.c中)  
  2. /* 
  3. * Initialise "virtual memory" maps 
  4. */  
  5. void vminit __P((void));  
  6. /*  sys/sys/cdefs.h 
  7.     #define __P(protos)  protos  /*full-blown ANSI C*/  
  8.     Void vminit __P((void ))也就是说vminit不带任何参数  
  9. */  
  10. void  
  11. vminit ()  
  12. {  
  13. extern int memorysize;      //  定义在pmon/common/main.c中  
  14. /*  memorysize在initmips中被初始化为: 
  15. *   memorysize = memsz > 256 ? 256 << 20 : memsz << 20; 
  16. *   memsz是在start.S中初始化的,为240 
  17. *  memorysize = 0x0f00 0000 
  18. */  
  19.     if (!kmem) {    //  static u_char *kmem;  
  20.         /* grab a chunk at the top of memory */  
  21.         if (memorysize < VM_KMEM_SIZE * 2) {  
  22.             panic ("not enough memory for network");  
  23.         }  
  24.         memorysize = (memorysize - VM_KMEM_SIZE) & ~PGOFSET;  
  25. #ifdef __mips__   
  26.         if ((u_int32_t)&kmem < (u_int32_t)UNCACHED_MEMORY_ADDR) {  
  27.             /* if linked for data in kseg0, keep kmem there too */  
  28.             kmem = (u_char *) PHYS_TO_CACHED (memorysize);  
  29.         }  
  30.         else {  
  31.             kmem = (u_char *) PHYS_TO_UNCACHED (memorysize);  
  32.         }  
  33. #else  
  34.         kmem = (u_char *)memorysize;      
  35. #endif  
  36.     }  
  37. vminit函数所作的事归纳起来就一件,即初始化kem这个静态全局变量:  
  38. kmem =  (u_char *) ((memorysize - VM_KMEM_SIZE) & ~PGOFSET);  
  39.  
  40. #define VM_KMEM_SIZE        (NKMEMCLUSTERS * CLBYTES)   //  2MB  
  41. #define  NKMEMCLUSTERS   (2048 * 1024 / CLBYTES)    /* 0.5Mb */  
  42. #define CLBYTES     (CLSIZE*NBPG)   //  4096  
  43. #define CLSIZE      1   //  1  
  44.  
  45. #define PGOFSET     (NBPG-1)    /* byte offset into page */  
  46. #define NBPG        4096        /* bytes/page */  
  47. PGOFSET 即为 4095(即一页的大小,4KB),4095 = 0x0FFF。  
  48.   
  49. 可以算得VM_KMEM_SIZE为 0x0020 0000,而memorysize为0x0F00 0000,  
  50. memory – VM_KMEM_SIZE = 0x0EE0 0000,  
  51. kmem =  (u_char *) PHYS_TO_UNCACHED (memorysize);  
  52.      = 0x8ee0 0000  
  53. 240 MB – 2MB;  
  54. 0……….………………………238MB(0x0ee0 0000)………..240MB  
  55.                           kmem(0x8ee0 0000)  
  56. vminit函数:  
  57. 将kmem指向内存的最后2MB处,并将其映射到kseg0地址空间;  
  58.   
  59.   
  60. 2.kmeminit(sys/kern/kern_malloc.c)  
  61. /* 
  62. * Initialise memory allocator 
  63. */  
  64. void  
  65. kmeminit()  
  66. {  
  67.     int npg;  
  68. //  检查MAXALLOCSAVE是否是2的幂  
  69. /* 
  70. #define MAXALLOCSAVE    (MINALLOCSIZE * 32768)   
  71. 0x8000 * 0x10 = 0x80000 
  72. #define MINALLOCSIZE    (1 << MINBUCKET)  // 0x10 
  73. #define  MINBUCKET  4       /* 4 => min allocation of 16 bytes */  
  74. */  
  75. #if ((MAXALLOCSAVE & (MAXALLOCSAVE - 1)) != 0)    
  76.         ERROR!_kmeminit:_MAXALLOCSAVE_not_power_of_2  
  77. #endif  
  78. #if (MAXALLOCSAVE > MINALLOCSIZE * 32768)  
  79.         ERROR!_kmeminit:_MAXALLOCSAVE_too_big  
  80. #endif  
  81. #if (MAXALLOCSAVE < CLBYTES)  
  82.         ERROR!_kmeminit:_MAXALLOCSAVE_too_small  
  83. #endif  
  84. #ifdef DIAGNOSTIC  
  85.     if (sizeof(struct freelist) > (1 << MINBUCKET))  
  86.         panic("kmeminit: minbucket too small/struct freelist too big");  
  87. #endif  
  88.     npg = VM_KMEM_SIZE/ NBPG;     
  89.     /*   
  90.     2MB/4096 = 512 (0x200) 
  91. */  
  92. kmemusage = (struct kmemusage *) kmem_alloc(kernel_map,  
  93.         (vsize_t)(npg * sizeof(struct kmemusage)));  
  94. /* 
  95. kmemusage是kern_malloc.c中定义的一个kmemusage结构体变量:用于记录页的使用情况; 
  96. struct kmemusage结构体说明: 
  97. Array of descriptors that describe the contents of each page 
  98. struct kmemusage { 
  99.     short ku_indx;      /* bucket index */  
  100.     union {  
  101.         u_short freecnt;/* for small allocations, free pieces in page */  
  102.         u_short pagecnt;/* for large allocations, pages alloced */  
  103.     } ku_un;  
  104. };  
  105. */  
  106.     kmem_map = kmem_suballoc(kernel_map, (vaddr_t *)&kmembase,  
  107.         (vaddr_t *)&kmemlimit, (vsize_t)(npg * NBPG), FALSE);  
  108. /* 
  109. kmem_map是sys/vm/vm_kern.h中定义的一个vm_map_t变量; 
  110. typedef struct vm_map *vm_map_t; 
  111. */  
  112. }  
  113. 2.1 kmem_alloc函数  
  114. kmem_alloc函数只调用了kmem_malloc (map, size, 0),其中map对应于kernel_map,size对应于(vsize_t)(npg * sizeof(struct kmemusage)),size = 512 * 4 = 2048  
  115.   
  116. kmemusage = (struct kmemusage *) kmem_alloc(kernel_map,  
  117.         (vsize_t)(npg * sizeof(struct kmemusage)));  
  118.   
  119. 下面即是kmem_malloc函数:  
  120. vm_offset_t  
  121. kmem_malloc (map, size, canwait)  
  122.     vm_map_t map;  
  123.     vm_size_t size;  
  124. {  
  125.     vm_offset_t p;  
  126.   
  127.     if(!kmem) { /* In case we call this before vminit() */  
  128.         vminit();  
  129.     }  
  130. /*PGOFSET 为4095 ,0x0FFF*/  
  131.     size = (size + PGOFSET) & ~PGOFSET; //size = 4096 = 0x1000  每次分配4KB对齐  
  132.     if (kmem_offs + size > VM_KMEM_SIZE) {  
  133.         log (LOG_DEBUG, "kmem_malloc: request for %d bytes fails/n", size);  
  134.         return 0;  
  135.     }  
  136.     p = (vm_offset_t) &kmem[kmem_offs]; //  kmem = 0x8ee0 0000  
  137.     kmem_offs += size;      //  kmem_offs = 4096  
  138.     return p;  
  139. }  
  140.   
  141. kernel_map = p = 0x8ee0 0000(kseg0段虚拟地址),即指向物理内存的238MB处;  
  142.   
  143.   
  144. 2.2 kmem_suballoc函数  
  145. vm_map_t  
  146. kmem_suballoc (map, base, lim, size, canwait)  
  147.     vm_map_t map;  
  148.     vm_offset_t *base, *lim;  
  149.     vm_size_t size;  
  150. {  
  151.     if (size > VM_KMEM_SIZE)  
  152.         panic ("kmem_suballoc");  
  153.     *base = (vm_offset_t) kmem;       
  154. /* 
  155.     kmem在vminit中被初始化为(u_char *) 0x0EE0 0000(指向物理内存238MB) 
  156.     typedef unsigned long       vm_offset_t; 
  157. typedef  unsigned long  vaddr_t; 
  158. base指向238MB 
  159. */  
  160. typedef unsigned long   vaddr_t;  
  161.     *lim = (vm_offset_t)  kmem + VM_KMEM_SIZE;  
  162. /*lim指向240MB*/  
  163.     return map;  
  164. }  
  165. 在kmeminit函数中:  
  166. kmem_map = kmem_suballoc(kernel_map, (vaddr_t *)&kmembase,  
  167.         (vaddr_t *)&kmemlimit, (vsize_t)(npg * NBPG), FALSE);  
  168. 最终执行的结果为:  
  169.     kmembase  === > 0x8ee0 0000(物理内存238MB )  
  170.     kmemlimit  === > 0x0F00 0000(物理内存240MB)  
  171.     kmem_map = kernel_map = 0x8ee0 0000  
 

 

kmembase、kmemlimit、kmem_map在内存分配函数中都会用到。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值