映射用户进程页表

remap_pfn_range函数用于将指定的物理页帧(pfn)映射到用户空间的地址范围,涉及页表结构如pgd、p4d、pud、pmd和pte的遍历与分配,以及pte_mkspecial进行特殊标记。该过程确保了内核能正确处理特殊的内存映射。
摘要由CSDN通过智能技术生成

映射用户进程页表

int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,unsigned long pfn, unsigned long size, pgprot_t prot)
    vma:进程的VMA
    addr:用户空间的地址
    pfn:指定页帧号
    size:需要映射的大小
    port:设置一些标志位

remap_pfn_range

int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
		    unsigned long pfn, unsigned long size, pgprot_t prot){
    struct mm_struct *mm = vma->vm_mm;//通过VMA获取mm数据结构
    err = track_pfn_remap(vma, &prot, remap_pfn, addr, PAGE_ALIGN(size));//判断映射是否合法,size为物理ddr的size
	if (err)
		return -EINVAL;
    
    vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;//这里的映射属于 special mapping 不让映射的页加入到内存管理里面
    
    pfn -= addr >> PAGE_SHIFT;
    pgd = pgd_offset(mm, addr);//通过mm和addr获取对应的pgd页表项
    
    do {
        /*以PGD_SIZE步长便利页表*/
		next = pgd_addr_end(addr, end);//获取下一个PGD页表项的范围的开始的地址
		err = remap_p4d_range(mm, pgd, addr, next,
				pfn + (addr >> PAGE_SHIFT), prot);//向下遍历页表
		if (err)
			break;
	} while (pgd++, addr = next, addr != end);
} 

比那里P4D页表

static inline int remap_p4d_range(struct mm_struct *mm, pgd_t *pgd,
			unsigned long addr, unsigned long end,
			unsigned long pfn, pgprot_t prot)
{
	p4d_t *p4d;
	unsigned long next;
	int err;

	pfn -= addr >> PAGE_SHIFT;
	p4d = p4d_alloc(mm, pgd, addr);//通过mm pgd addr找到对应的p4d页表项,
	if (!p4d)
		return -ENOMEM;
	do {
		next = p4d_addr_end(addr, end);
		err = remap_pud_range(mm, p4d, addr, next,
				pfn + (addr >> PAGE_SHIFT), prot);//遍历下一级页表
		if (err)
			return err;
	} while (p4d++, addr = next, addr != end);//步长为P4D
	return 0;
}

遍历PUD页表:

static inline int remap_pud_range(struct mm_struct *mm, p4d_t *p4d,
			unsigned long addr, unsigned long end,
			unsigned long pfn, pgprot_t prot)
{
	pud_t *pud;
	unsigned long next;
	int err;

	pfn -= addr >> PAGE_SHIFT;
	pud = pud_alloc(mm, p4d, addr);//通过mm, p4d, addr找到PUD页表项
	if (!pud)
		return -ENOMEM;
	do {
		next = pud_addr_end(addr, end);//获取下一个PUD页表项管理地址的首地址
		err = remap_pmd_range(mm, pud, addr, next,
				pfn + (addr >> PAGE_SHIFT), prot);//开始遍历下一级PMD页表
		if (err)
			return err;
	} while (pud++, addr = next, addr != end);//以PUD_SIZE为步长开始遍历
	return 0;
}
remap_p4d_range
   p4d = p4d_alloc(mm, pgd, addr);//通过mm pgd addr找到对应的p4d页表项
   err = remap_pud_range(mm, p4d, addr, next,pfn + (addr >> PAGE_SHIFT), prot);//开始遍历pud页表
    	pud = pud_alloc(mm, p4d, addr);//通过mm, p4d, addr找到对应的PUD页表项
		err = remap_pmd_range(mm, pud, addr, next,pfn + (addr >> PAGE_SHIFT), prot);//开始遍历PMD页表
			pmd = pmd_alloc(mm, pud, addr);//通过mm, pud, addr找到PMD
			err = remap_pte_range(mm, pmd, addr, next,pfn + (addr >> PAGE_SHIFT), prot);//开始遍历下一级PTE
				/*将一系列物理内存映射到所请求的页面中*/
				pte = pte_alloc_map_lock(mm, pmd, addr, &ptl);//通过mm, pmd, addr找到对应的PTE页表项,申请一个spinkock锁ptl
				set_pte_at(mm, addr, pte, pte_mkspecial(pfn_pte(pfn, prot)));//pte 设置到硬件页表中去    页表项(PTE)----> 硬件页表
																			 //pfn_pte :通过pfn获取到pte
																			// pte_mkspecial 设置软件的PTE_SPECIAL标志位
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DipsyHu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值