集群系统MOSIX分析(5)
2008-12-01 11:04:43 来源:WEB开发网物理页面:
Linux采用"按需调页"(demand paging)算法,支持三层页式存储管理策略。第一级是页目录(pgd),第二级是页中间目录(pmd),第三级是页表(pte)。页表由页表项组成,每个页表项保存着物理内存页的首址和页属性。task_struct的数据成员mm的pgd成员为进程页目录的起始地址。Linux提供了一系列宏将虚地址转换成物理地址。下面给出一段示例性代码,将虚地址vaddr转换成物理地址addr:
unsigned char* GeuphyAddr(struct vm_area_struct* vma,unsigned long vaddr)
{
pgd_t *pgdir; pmd_t *pmdir; pte_t *pte;
pgdir = pgd_offset(vma->vm_mm, vaddr);
if(pgd_none(*pgdir) ||pgd_bad(*pgdir))
return -EINVAL;
pmdir = pmd_offset(pgdir, vaddr);
if(pmd_none(*pmdir) ||pmd_bad(*pmdir))
return -EINVAL;
pte = pte_offset(pmdir, vaddr);
if(pte_present(*pte) )
{addr=(unsigned char )pte_page(*pte);return addr;}
return -EINVAL;
}
对进程的每个VMA,以物理页面大小(I386结构为4K)为间隔,分别进行三级地址映射,得到物理页面的起始地址,将物理内存依次拷贝到远程节点。远程节点则分配物理页面,在目的进程b上建立相应的页表项。下面给出一段示例性代码,接收一个页面:
int receive_page(unsigned long addr)
{
pgd_t * pgd; pmd_t * pmd; pte_t * pte;
unsigned long page = 0;
struct vm_area_struct * vma;
struct task_struct *p = current
if(!(vma = find_vma(p->mm, addr)))
return -EINVAL;
if(!(page = __get_free_page(GFP_KERNEL)))
return -EINVAL;
/*从接收到的数据中拷贝PAGE_SIZE 大小的数据到page指向的区域*/
CopyData((void *)page, PAGE_SIZE, 0)) ;
/*建立并设置新的页表项 */
pgd = pgd_offset(p->mm, addr);
if (!(pmd = pmd_alloc(pgd, addr))) return -EINVAL;
if (!(pte = pte_alloc(pmd, addr))) return -EINVAL;
if (!pte_none(*pte)) return -EINVAL;
set_pte(pte, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
}
更多精彩
赞助商链接