当前位置: 首页 > 面试题库 >

如何从Linux内核模块中的逻辑地址获取物理地址?

蔡弘扬
2023-03-14
问题内容

除了手动浏览页面目录条目之外,是否有任何合适的方法可以通过逻辑地址获取物理地址?我在内核的源代码中寻找了此功能,并发现有一个follow_page功能可以很好地利用内置的巨大和透明页面支持。但是它没有导出到内核模块(为什么?)…

因此,我不想发明轮子,我认为follow_page手动重新实现功能不是很好。


问题答案:

好吧,它看起来可能像这样(在虚拟地址后跟随PTE):

void follow_pte(struct mm_struct * mm, unsigned long address, pte_t * entry)
{
    pgd_t * pgd = pgd_offset(mm, address);

    printk("follow_pte() for %lx\n", address);

    entry->pte = 0;
    if (!pgd_none(*pgd) && !pgd_bad(*pgd)) {
        pud_t * pud = pud_offset(pgd, address);
        struct vm_area_struct * vma = find_vma(mm, address);

        printk(" pgd = %lx\n", pgd_val(*pgd));

        if (pud_none(*pud)) {
            printk("  pud = empty\n");
            return;
        }
        if (pud_huge(*pud) && vma->vm_flags & VM_HUGETLB) {
            entry->pte = pud_val(*pud);
            printk("  pud = huge\n");
            return;
        }

        if (!pud_bad(*pud)) {
            pmd_t * pmd = pmd_offset(pud, address);

            printk("  pud = %lx\n", pud_val(*pud));

            if (pmd_none(*pmd)) {
                printk("   pmd = empty\n");
                return;
            }
            if (pmd_huge(*pmd) && vma->vm_flags & VM_HUGETLB) {
                entry->pte = pmd_val(*pmd);
                printk("   pmd = huge\n");
                return;
            }
            if (pmd_trans_huge(*pmd)) {
                entry->pte = pmd_val(*pmd);
                printk("   pmd = trans_huge\n");
                return;
            }
            if (!pmd_bad(*pmd)) {
                pte_t * pte = pte_offset_map(pmd, address);

                printk("   pmd = %lx\n", pmd_val(*pmd));

                if (!pte_none(*pte)) {
                    entry->pte = pte_val(*pte);
                    printk("    pte = %lx\n", pte_val(*pte));
                } else {
                    printk("    pte = empty\n");
                }
                pte_unmap(pte);
            }
        }
    }
}


 类似资料:
  • 主要内容:物理地址空间,逻辑地址空间,什么是单词?物理地址空间 系统中的物理地址空间可以被定义为主存储器的大小。 将进程大小与物理地址空间进行比较非常重要。 进程大小必须小于物理地址空间。 逻辑地址空间 逻辑地址空间可以定义为进程的大小。 进程的大小应该足够小,以便它可以驻留在主内存中。 什么是单词? Word是内存的最小单位。 它是字节的集合。 在分析输入到解码器的n位地址和从解码器产生的2 ^ n个存储位置之后,每个操作系统定义不同的字长。

  • 问题内容: 到目前为止,我使用PyQt类所做的事情: 输出: 使用: 输出: 有没有办法区分它们? 可以使用普通的Python代替PyQt类吗? 如何获得IPv6地址? 问题答案: 您应该使用netifaces。它被设计为跨平台的,并且包含Windows专用代码以及可在不同UNIX / UNIX类平台上工作的各种通用版本。 从netifaces版本0.10.0开始,支持Python3。 使用摘要

  • 从虚拟内存到物理内存 虚拟地址和物理地址 到目前为止,我们简易的操作系统还只是一个内核在执行,还没有多任务的概念。在现代的操作系统中,为了让其他的程序能方便的运行在操作系统上,需要完成的一个很重要的抽象是「每个程序有自己的地址空间,且地址空间范围是一样的」,这将会减少了上层程序的大量麻烦,否则程序本身要维护自己需要的物理内存,这也会导致极大程度的不安全。 这个执行上看到的地址空间,就是虚拟内存。而

  • 问题内容: 我正在一个小型嵌入式系统上工作。当我的linux启动到用户空间时,我知道物理内存中的设备在哪里。我想将它们映射到用户空间虚拟地址。目前,我正在通过内核模块进行操作。我使用vmalloc / kmalloc(取决于大小),然后在返回的虚拟地址上使用ioremap_page_range映射我的物理地址。我不认为这是正确的方法。首先,我分配内存,然后要求内核将虚拟地址空间重新映射到一些不同的

  • 问题内容: 在运行Linux的基于ARM的系统上,我有一个将内存映射到物理地址的设备。从所有地址都是虚拟的用户空间程序中,如何从该地址读取内容? 问题答案: 您可以使用系统调用将设备文件映射到用户进程内存。通常,设备文件是物理内存到文件系统的映射。否则,您必须编写一个内核模块来创建此类文件或提供一种将所需内存映射到用户进程的方法。 另一种方法是将/ dev / mem的部分重新映射到用户内存。 编

  • 我在服务器上执行如下命令: netstat -anp | grep 6379 查看redis的6379端口情况,结果如下所示: 上面的192.168.0.11是内网地址,41.92.250.40是公网地址(当然为了安全我这边是随便改了不是真实的地址) 阿某云买的服务器,上面有两个ip 41.92.250.40(公) 192.168.0.11(私有) 现在我对Local Address 本地地址还有