xv6 的分配函数中的释放函数是什么
what does deallocation function in xv6's allocation function
对于情况1和2,释放函数在分配函数中做了什么?
case 1: if(mem == 0)
// does this condition mean physical memory has not space?
case 2: if(mappages(pgdir, (char*)a, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0)
// does this condtion mean pagetable entry has not allocate in physical memory?
我附加了释放函数和分配函数。
参考:
https://github.com/fernandabonetti/xv6/blob/master/vm.c
int
allocuvm(pde_t *pgdir, uint oldsz, uint newsz)
{
char *mem;
uint a;
if(newsz >= KERNBASE)
return 0;
if(newsz < oldsz)
return oldsz;
a = PGROUNDUP(oldsz);
for(; a < newsz; a += PGSIZE){
mem = kalloc();
if(mem == 0){
cprintf("allocuvm out of memory\n");
deallocuvm(pgdir, newsz, oldsz);
return 0;
}
memset(mem, 0, PGSIZE);
if(mappages(pgdir, (char*)a, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0){
cprintf("allocuvm out of memory (2)\n");
deallocuvm(pgdir, newsz, oldsz);
kfree(mem);
return 0;
}
}
return newsz;
}
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);
if(!pte)
a = PGADDR(PDX(a) + 1, 0, 0) - PGSIZE;
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;
}
allocuvm 是分配用户虚拟内存的缩写。该函数负责增加用户在特定页面目录中的虚拟内存。
这个函数确实有 2 种情况会失败:
情况一:kalloc函数失败。 kalloc 是内核分配的简称。该函数负责 return RAM 中一个新的、当前未使用的页面的地址。如果returns 0,则表示当前没有可用的未使用页面。
情况2:映射页面功能失败。此函数负责通过将该页面映射到页面目录中的下一个可用虚拟地址,使使用给定页面目录的进程可以访问新分配的页面。
如果此功能失败,则意味着它失败了,可能是因为页面目录已经满了。
在这两种情况下,allocuvm 都没有设法将用户的内存增加到请求的大小,因此,它会撤消所有分配,直到出现故障点,因此虚拟内存将保持不变,并且 return本身就是一个错误。
对于情况1和2,释放函数在分配函数中做了什么?
case 1: if(mem == 0)
// does this condition mean physical memory has not space?
case 2: if(mappages(pgdir, (char*)a, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0)
// does this condtion mean pagetable entry has not allocate in physical memory?
我附加了释放函数和分配函数。
参考: https://github.com/fernandabonetti/xv6/blob/master/vm.c
int
allocuvm(pde_t *pgdir, uint oldsz, uint newsz)
{
char *mem;
uint a;
if(newsz >= KERNBASE)
return 0;
if(newsz < oldsz)
return oldsz;
a = PGROUNDUP(oldsz);
for(; a < newsz; a += PGSIZE){
mem = kalloc();
if(mem == 0){
cprintf("allocuvm out of memory\n");
deallocuvm(pgdir, newsz, oldsz);
return 0;
}
memset(mem, 0, PGSIZE);
if(mappages(pgdir, (char*)a, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0){
cprintf("allocuvm out of memory (2)\n");
deallocuvm(pgdir, newsz, oldsz);
kfree(mem);
return 0;
}
}
return newsz;
}
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);
if(!pte)
a = PGADDR(PDX(a) + 1, 0, 0) - PGSIZE;
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;
}
allocuvm 是分配用户虚拟内存的缩写。该函数负责增加用户在特定页面目录中的虚拟内存。 这个函数确实有 2 种情况会失败:
情况一:kalloc函数失败。 kalloc 是内核分配的简称。该函数负责 return RAM 中一个新的、当前未使用的页面的地址。如果returns 0,则表示当前没有可用的未使用页面。
情况2:映射页面功能失败。此函数负责通过将该页面映射到页面目录中的下一个可用虚拟地址,使使用给定页面目录的进程可以访问新分配的页面。 如果此功能失败,则意味着它失败了,可能是因为页面目录已经满了。
在这两种情况下,allocuvm 都没有设法将用户的内存增加到请求的大小,因此,它会撤消所有分配,直到出现故障点,因此虚拟内存将保持不变,并且 return本身就是一个错误。