Xv6学习之kinit1

来源:互联网 发布:小学电脑绘画软件 编辑:程序博客网 时间:2024/05/18 02:11

位置:进入主函数执行的第一个函数

kinit1(end, P2V(4*1024*1024)); // phys page allocator


void
kinit1(void *vstart, void *vend)
{
  initlock(&kmem.lock, "kmem");
  kmem.use_lock = 0;
  freerange(vstart, vend);
}


void
initlock(struct spinlock *lk, char *name)
{
  lk->name = name;
  lk->locked = 0;
  lk->cpu = 0;
}


void
kfree(char *v)
{
  struct run *r;


  if((uint)v % PGSIZE || v < end || v2p(v) >= PHYSTOP)
    panic("kfree");


  // Fill with junk to catch dangling refs.
  memset(v, 1, PGSIZE);


  if(kmem.use_lock)
    acquire(&kmem.lock);
  r = (struct run*)v;
  r->next = kmem.freelist;
  kmem.freelist = r;
  if(kmem.use_lock)
    release(&kmem.lock);
}



####:物理内存分配器
分配器中的数据构是⼀个由可分配物理内存构成的*空 表*个空闲页表的元素是构体
`struct run`2764)。那么分配器从哪⾥得内存来存放些数据构呢?实际上,分配器将每个空
闲页`run`构体保存在闲页本身中,因闲页中没有其他数据。分配器⽤⼀个spin lock
2764-2766)来保闲链表。表和都封装在⼀个构体中,这样逻辑就比明晰:
该结构体中的域。不过现先忽略,以及`acquire``release`⽤;我会在
4 章了解其细节
`main`函数⽤了`kinit1``kinit2`两个函数分配器⾏初始化(2780)。这样做是由于
`main`中的⼤部分代都不能使⽤以及4MB以上的内存。`kinit1`在前4MB ⾏了不需要的内
存分配。⽽ `kinit2` 的使⽤,并使得更多的内存可⽤于分配。原本应该`main`决定有多
少物理内存可⽤于分配,但在 x86 上很难实现所以它假机器中有240MB`PHYSTOP`)物理内存,
并将内核末尾和 `PHYSTOP`的内存都作⼀个初始的空内存池。`kinit1``kinit2`
`freerange`将内存加入空闲链表中,`freerange`是通过对每⼀页调`kfree`实现该功能。⼀
PTE只能指向⼀个4096节对齐的物理地址(即是4096的倍数),因此`freerange`
`PGROUNDUP`来保分配器只会对齐的物理地址。分配器原本⼀开始没有内存可⽤,正是
`kfree`⽤将可⽤内存交了分配器来管理。
分配器⽤映射到⾼内存区域的虚地址找到对应的物理,⽽⾮物理地址。所以`kinit`会使⽤ `p2v
(PHYSTOP)`来将`PHYSTOP`(⼀个物理地址)翻译为地址。分配器有将地址看作是整型,
⾏运算(譬如在`kinit`中遍所有);⽽有将地址看作写内存⽤的指(譬如操作每
中的`run`构体);地址的双重使⽤致分配器代中充了类型转换。另外⼀个原因是,
放和分配内存性地改了内存的类型。
函数 `kfree`2815)首先将被放内存的每⼀字节设为1使得访问已被放内存的代到的
不是原有数据,⽽是垃圾数据;这样做能让这错误的代尽早崩。接下来`kfree``v` 转换为
⼀个指向构体`struct run`的指,在`r->next`中保存原有空闲链表的表,然后将当前的空
闲链`r``kalloc`移除并返回空闲链表的表





1 0
原创粉丝点击