deallocuvm 在 Xv6 中如何工作?
How does deallocuvm work in Xv6?
根据源代码中的注释,deallocate 确实解除分配用户页面,将进程大小从 oldsz 带到 newsz
我的问题是当 pte 不存在时,它应该继续搜索下一个页面目录条目,但是为什么 PGADDR(PDX(a) + 1, 0, 0) 应该在这里减去 PGSIZE。
if(!pte)
a = PGADDR(PDX(a) + 1, 0, 0) - PGSIZE;
这是来自 Xv6 的源代码:
int
deallocuvm(pde_t *pgdir, uint oldsz, uint newsz)
{
pte_t *pte;
uint a, pa;
if(newsz >= oldsz)
return oldsz;
a = PGROUNDUP(newsz);
for(; a < oldsz; a += PGSIZE){
pte = walkpgdir(pgdir, (char*)a, 0);
// pte not exists to next page table dir
// do not understand why should minus PGSIZE
if(!pte)
a = PGADDR(PDX(a) + 1, 0, 0) - PGSIZE;
// pte exists
else if((*pte & PTE_P) != 0){
pa = PTE_ADDR(*pte);
if(pa == 0)
panic("kfree");
char *v = P2V(pa);
kfree(v);
*pte = 0;
}
}
return newsz;
}
for
循环执行 a += PGSIZE
。每次循环迭代时它都会这样做。
如果在进入下一个 PDE 时未减去 PGSIZE
,则 a
将在下一次迭代中减少 PGSIZE
个元素。
根据源代码中的注释,deallocate 确实解除分配用户页面,将进程大小从 oldsz 带到 newsz
我的问题是当 pte 不存在时,它应该继续搜索下一个页面目录条目,但是为什么 PGADDR(PDX(a) + 1, 0, 0) 应该在这里减去 PGSIZE。
if(!pte)
a = PGADDR(PDX(a) + 1, 0, 0) - PGSIZE;
这是来自 Xv6 的源代码:
int
deallocuvm(pde_t *pgdir, uint oldsz, uint newsz)
{
pte_t *pte;
uint a, pa;
if(newsz >= oldsz)
return oldsz;
a = PGROUNDUP(newsz);
for(; a < oldsz; a += PGSIZE){
pte = walkpgdir(pgdir, (char*)a, 0);
// pte not exists to next page table dir
// do not understand why should minus PGSIZE
if(!pte)
a = PGADDR(PDX(a) + 1, 0, 0) - PGSIZE;
// pte exists
else if((*pte & PTE_P) != 0){
pa = PTE_ADDR(*pte);
if(pa == 0)
panic("kfree");
char *v = P2V(pa);
kfree(v);
*pte = 0;
}
}
return newsz;
}
for
循环执行 a += PGSIZE
。每次循环迭代时它都会这样做。
如果在进入下一个 PDE 时未减去 PGSIZE
,则 a
将在下一次迭代中减少 PGSIZE
个元素。