动手实践-把内存地址转化成物理地址

动手实践-把内存地址转化成物理地址

创建vaddr2paddr.c文件

#include<linux/init.h>
#include<linux/module.h>
#include<linux/mm.h>
#include<linux/mm_types.h>
#include<linux/sched.h>
#include<linux/export.h>

static unsigned long cr0,cr3;
static unsigned long vaddr=0;

static void get_pgtable_macro(void)
{
    cr0=read_cr0();
    cr3=read_cr3_pa();
    
    printk("cr0=0x%lx,cr3=0x%lx\n",cr0,cr3);

    printk("PGDIR_SHIFT=%d\n",PGDIR_SHIFT);
    printk("P4D_SHIFT=%d\n",P4D_SHIFT);
    printk("PUD_SHIFT=%d\n",PUD_SHIFT);
    printk("PMD_SHIFT=%d\n",PMD_SHIFT);
    printk("PAGE_SHIFT=%d\n",PAGE_SHIFT);
    
    printk("PTRS_PER_PGD=%d\n",PTRS_PER_PGD);
    printk("PTRS_PER_P4D=%d\n",PTRS_PER_P4D);
    printk("PTRS_PER_PUD=%d\n",PTRS_PER_PUD);
    printk("PTRS_PER_PMD=%d\n",PTRS_PER_PMD);
    printk("PTRS_PER_PTE=%d\n",PTRS_PER_PTE);
    printk("PAGE_MASK=0x%lx\n",PAGE_MASK);
}


static unsigned long vaddr2paddr(unsigned long vaddr)
{
    pgd_t *pgd;
    p4d_t *p4d;
    pud_t *pud;
    pmd_t *pmd;
    pte_t *pte;
    
    unsigned long paddr=0;
    unsigned long page_addr=0;
    unsigned long page_offset=0;
    pgd=pgd_offset(current->mm,vaddr);
    printk("pgd_offset=ox%lx,pgd_index=%lu\n",pgd_val(*pgd),pgd_index(vaddr));
    if(pgd_none(*pgd))
    {
        printk("not mapped in pgd\n");
        return -1;
    }

    p4d=p4d_offset(pgd,vaddr);
    printk("p4d_offset=ox%lx,p4d_index=%lu\n",p4d_val(*p4d),p4d_index(vaddr));
    if(p4d_none(*p4d))
    {
        printk("not mapped in p4d\n");
        return -1;
    }

    pud=pud_offset(p4d,vaddr);
    printk("pud_offset=ox%lx,pud_index=%lu\n",pud_val(*pud),pud_index(vaddr));
    if(pud_none(*pud))
    {
        printk("not mapped in pud\n");
        return -1;
    }

    pmd=pmd_offset(pud,vaddr);
    printk("pmd_offset=ox%lx,pmd_index=%lu\n",pmd_val(*pmd),pmd_index(vaddr));
    if(pmd_none(*pmd))
    {
        printk("not mapped in pmd\n");
        return -1;
    }

    pte=pte_offset_kernel(pmd,vaddr);
    printk("pte_offset=ox%lx,pte_index=%lu\n",pte_val(*pte),pte_index(vaddr));
    if(pte_none(*pte))
    {
        printk("not mapped in pte\n");
        return -1;
    }

    page_addr=pte_val(*pte)&PAGE_MASK;
    page_offset=vaddr&~PAGE_MASK;
    paddr=page_addr|page_offset;
    printk("page_addr=0x%lx,page_offset=0x%lx\n",page_addr,page_offset);
    printk("vaddr=0x%lx,paddr=0x%lx\n",vaddr,paddr);

    return paddr;
}

static int __init v2p_init(void)
{
    unsigned long vaddr=0;
    printk("vaddr to paddr module is running..\n");
    get_pgtable_macro();
    printk("\n");
    vaddr=__get_free_page(GFP_KERNEL);
    if(vaddr==0)
    {
        printk("__get_free_page failed..\n");
        return 0;
    }

    sprintf((char *)vaddr,"hello world from kernel");
    printk("get_page_vaddr=0x%lx\n",vaddr);
    vaddr2paddr(vaddr);
    return 0;
}

static void __exit v2p_exit(void)
{
    printk("vaddr to paddr module is leaving..\n");
    free_page(vaddr);
}

module_init(v2p_init);
module_exit(v2p_exit);

创建Makefile文件

obj-m:=vaddr2paddr.o
	
CURRENT_PAHT:=$(shell pwd)
LINUX_KERNEL:=$(shell uname -r)
LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)

all:
	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PAHT) modules
clean:
	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PAHT) clean

输出日志文件内容
在这里插入图片描述


版权声明:本文为qq_38966867原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。