• 手动模拟 Linux 内核 mmu 内存寻址


    每个页的大小: 2^12 = 4096 Bytes

    每个地址的大小: 8 Bytes

    每个页能容纳:2^9 = 512 个地址

    需要一个 9bit 的字段来索引映射表

    一般来说,如果页面大小为 2^k,那么一个页面可以容纳 k-3 个指针

    #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;
    static unsigned long 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
    ", cr0, cr3);
    
            printk("PGDIR_SHIFT = %d
    ", PGDIR_SHIFT);
            printk("P4D_SHIFT = %d
    ", P4D_SHIFT);
            printk("PUD_SHIFT = %d
    ", PUD_SHIFT);
            printk("PMD_SHIFT = %d
    ", PMD_SHIFT);
            printk("PAGE_SHIFT = %d
    ", PAGE_SHIFT);
    
            //页目录表中项的个数
            printk("PTRS_PER_PGD = %d
    ", PTRS_PER_PGD);
            printk("PTRS_PER_P4D = %d
    ", PTRS_PER_P4D);
            printk("PTRS_PER_PUD = %d
    ", PTRS_PER_PUD);
            printk("PTRS_PER_PMD = %d
    ", PTRS_PER_PMD);
            printk("PTRS_PER_PTE = %d
    ", PTRS_PER_PTE);
    
            //页内偏移掩码,用来屏蔽 page_offset
            printk("PAGEMASK = 0x%lx
    ", PAGE_MASK);
    }
    
    void 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_val = 0x%lx, pgd_index = %lu
    ", pgd_val(*pgd), pgd_index(vaddr));
    
            //取得 p4d
            p4d = p4d_offset(pgd, vaddr);
            printk("p4d_val = 0x%lx, p4d_index = %lu
    ", p4d_val(*p4d), p4d_index(vaddr));
    
            //取得页上级目录项
            pud = pud_offset(p4d, vaddr);
            printk("pud_val = 0x%lx, pud_index = %lu
    ", pud_val(*pud), pud_index(vaddr));
    
            //取得页中间目录项
            pmd = pmd_offset(pud, vaddr);
            printk("pmd_val = 0x%lx, pmd_index = %lu
    ", pmd_val(*pmd), pmd_index(vaddr));
    
            //取得页表(在主内核页表中查找)
            pte = pte_offset_kernel(pmd, vaddr);
            printk("pte_val = 0x%lx, pte_index = %lu
    ", pte_val(*pte), pte_index(vaddr));
    
            //取得的页表项的低 12 位放的是页属性
            //所以用 PAGE_MASK 来清除
            page_addr = pte_val(*pte) & PAGE_MASK;
            
            //取得页内偏移 page_offset
            //也就是只取虚拟地址的地 12 位
            page_offset = vaddr & ~PAGE_MASK;
    
            //然后和并页表地址和页内偏移取得物理地址
            paddr = page_addr | page_offset;
    
            printk("page_addr = 0x%lx, page_offset = 0x%lx
    ", page_addr, page_offset);
            printk("virtual address = 0x%lx, physical address = 0x%lx
    ", vaddr, paddr);
    
    }
    
    static int __init v2p_init(void)
    {
            unsigned long vaddr = 0;
            printk("vritual address to physical address module is running..
    ");
            get_pgtable_macro();
            printk("
    ");
            vaddr = __get_free_page(GFP_KERNEL);
            if(vaddr == 0)
            {
                    printk("__get_free_page failed..
    ");
                    return 0;
            }
            printk("get_page_vaddr = 0x%lx
    ", vaddr);
            vaddr2paddr(vaddr);
            return 0;
    }
    
    static void __exit v2p_exit(void)
    {
            free_page(vaddr);
            printk("module is leaving...
    ");
    }
    
    
    module_init(v2p_init);
    module_exit(v2p_exit);
    
  • 相关阅读:
    [j2me]KSoap2在Nokia真机上可能导致SymbianOS error 28
    [J2ME]Nokia播放音乐时发生MediaException的解决办法
    [j2me]利用JLayerMECLDC0.2播放MP3的试验[1]
    [j2me]手机也可以玩播客(Podcast)! Geek开发说明[开源]
    [JavaME]手机申请移动分配的动态IP(3)?
    [流媒体]实例解析MMS流媒体协议,下载LiveMediaVideo[1][修正版,增加了带宽测试包]
    [JavaME]手机申请移动分配的动态IP(2)?
    [JavaME]手机是否能够申请到动态IP?
    [收藏]MIDlet如何签名的tutorial
    [流媒体]实例解析MMS流媒体协议,下载LiveMediaVideo[3]
  • 原文地址:https://www.cnblogs.com/crybaby/p/12940241.html
Copyright © 2020-2023  润新知