什么是逻辑地址?什么是物理地址

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是逻辑地址?什么是物理地址相关的知识,希望对你有一定的参考价值。

逻辑地址: 是指由程序产生的与段相关的偏移地址部分。又称绝对地址。

物理地址:在存储器里以字节为单位存储信息,为正确地存放或取得信息,每一个字节单元给以一个唯一的存储器地址,称为物理地址,又叫实际地址或绝对地址。

一、关系:逻辑地址和物理地址相对的。物理地址是唯一的,逻辑地址的相对的。 

二、表达方式:

1、逻辑地址:其表达形式为“段地址:段内偏移地址”。

2、物理地址:CPU与存储器进行数据交换时在地址总线上 。

扩展资料:

一、逻辑地址的产生背景

追根求源,Intel的8位机8080CPU,数据总线(DB)为8位,地址总线(AB)为16位。那么这个16位地址信息也是要通过8位数据总线来传送,也是要在数据通道中的暂存器,以及在CPU中的寄存器和内存中存放的,但由于AB正好是DB的整数倍,故不会产生矛盾!

但当上升到16位机后,Intel8086/8088CPU的设计由于当年IC集成技术和外封装及引脚技术的限制,不能超过40个引脚。但又感觉到8位机原来的地址寻址能力2^16=64KB太少了,但直接增加到16的整数倍即令AB=32位又是达不到的。

故而只能把AB暂时增加4条成为20条。则2^20=1MB的寻址能力已经增加了16倍。但此举却造成了AB的20位和DB的16位之间的矛盾,20位地址信息既无法在DB上传送,又无法在16位的CPU寄存器和内存单元中存放。于是应运而生就产生了CPU段结构的原理。

二、物理地址的计算方法

在实地址方式下,物理地址是通过段地址乘以16加上偏移地址得到的。而16位的段地址乘以16等同于左移4位二进制位,这样变成20位的段基地址,最后段基地址加上段内偏移地址即可得到物理地址。

20位物理地址计算方法如下:

物理地址=段地址*16d+偏移地址。

参考资料:百度百科-逻辑地址

参考资料:百度百科-物理地址

参考技术A

在有地址变换功能的计算机中,访问指令给出的地址 (操作数) 叫逻辑地址,也叫相对地址。

要经过寻址方式的计算或变换才得到内存储器中的物理地址。

1、把用户程序中使用的地址称为相对地址即逻辑地址。

2、逻辑地址由两个16位的地址分量构成,一个为段基值,另一个为偏移量。两个分量均为无符号数编码。

各种计算机的寻址方式 (地址变换功能)都有所不同,在用汇编语言编写程序时,要先熟悉这个机器的指令系统。

扩展资料:

在网络底层的物理传输过程中,是通过物理地址来识别主机的,它一般也是全球唯一的。比如,著名的以太网卡,其物理地址大小是48bit(比特位),前24位是厂商编号,后24位为网卡编号,如:44-45-53-54-00-00,以机器可读的方式存入主机接口中。

以太网地址管理机构(IEEE)将以太网地址,也就是48比特的不同组合,分为若干独立的连续地址组,生产以太网网卡的厂家就购买其中一组,具体生产时,逐个将唯一地址赋予以太网卡。

参考资料来源:百度百科-逻辑地址

参考技术B

物理地址是针对硬件的唯一对应且不可更改的地址;逻辑地址是随环境变化而可变可修改的地址

如图中电脑网络的地址:“实际地址”就是物理地址,是针对本机网卡的唯一地址,全球仅此一个,是不可变的,此地址在硬件出厂时就已经设定好。“IP地址”就是逻辑地址,是根据路由器或者交换机分配或者获取的可变的地址。

物理地址就是唯一的,按照物理硬件定义的地址
逻辑地址就是认为规定的,方便通讯的而定义的地址
比如物理地址是A,他可能有很多逻辑地址,可能是为了方便记忆,可能是为了容易为人们所辨别,可能是为了便于网络管理.

物理地址(Physical Address) 是指出现在CPU外部地址总线上的寻址物理内存的地址信号,是地址变换的最终结果地址。如果启用了分页机制,那么线性地址会使用页目录和页表中的项变换成物理地址。如果没有启用分页机制,那么线性地址就直接成为物理地址了。

逻辑地址(Logical Address) 是指由程序产生的与段相关的偏移地址部分。例如,你在进行C语言指针编程中,可以读取指针变量本身值(&操作),实际上这个值就是逻辑地址,它是相对于你当前进程数据段的地址,不和绝对物理地址相干。只有在Intel实模式下,逻辑地址才和物理地址相等(因为实模式没有分段或分页机制,Cpu不进行自动地址转换);逻辑也就是在Intel 保护模式下程序执行代码段限长内的偏移地址(假定代码段、数据段如果完全一样)。应用程序员仅需与逻辑地址打交道,而分段和分页机制对您来说是完全透明的,仅由系统编程人员涉及。应用程序员虽然自己可以直接操作内存,那也只能在操作系统给你分配的内存段操作。

参考技术C 逻辑地址(Logical Address) 是指由程序产生的与段相关的偏移地址部分。例如,你在进行C语言指针编程中,可以读取指针变量本身值(&操作),实际上这个值就是逻辑地址,它是相对于你当前进程数据段的地址,不和绝对物理地址相干。只有在Intel实模式下,逻辑地址才和物理地址相等(因为实模式没有分段或分页机制,Cpu不进行自动地址转换);逻辑也就是在Intel 保护模式下程序执行代码段限长内的偏移地址(假定代码段、数据段如果完全一样)。应用程序员仅需与逻辑地址打交道,而分段和分页机制对您来说是完全透明的,仅由系统编程人员涉及。应用程序员虽然自己可以直接操作内存,那也只能在操作系统给你分配的内存段操作。

线性地址(Linear Address) 是逻辑地址到物理地址变换之间的中间层。程序代码会产生逻辑地址,或者说是段中的偏移地址,加上相应段的基地址就生成了一个线性地址。如果启用了分页机制,那么线性地址可以再经变换以产生一个物理地址。若没有启用分页机制,那么线性地址直接就是物理地址。Intel 80386的线性地址空间容量为4G(2的32次方即32根地址总线寻址)。

物理地址(Physical Address) 是指出现在CPU外部地址总线上的寻址物理内存的地址信号,是地址变换的最终结果地址。如果启用了分页机制,那么线性地址会使用页目录和页表中的项变换成物理地址。如果没有启用分页机制,那么线性地址就直接成为物理地址了。

虚拟内存(Virtual Memory) 是指计算机呈现出要比实际拥有的内存大得多的内存量。因此它允许程序员编制并运行比实际系统拥有的内存大得多的程序。这使得许多大型项目也能够在具有有限内存资源的系统上实现。一个很恰当的比喻是:你不需要很长的轨道就可以让一列火车从上海开到北京。你只需要足够长的铁轨(比如说3公里)就可以完成这个任务。采取的方法是把后面的铁轨立刻铺到火车的前面,只要你的操作足够快并能满足要求,列车就能象在一条完整的轨道上运行。这也就是虚拟内存管理需要完成的任务。在Linux 0.11内核中,给每个程序(进程)都划分了总容量为64MB的虚拟内存空间。因此程序的逻辑地址范围是0x0000000到0x4000000。

有时我们也把逻辑地址称为虚拟地址。因为与虚拟内存空间的概念类似,逻辑地址也是与实际物理内存容量无关的。
逻辑地址与物理地址的“差距”是0xC0000000,是由于虚拟地址->线性地址->物理地址映射正好差这个值。这个值是由操作系统指定的。本回答被提问者采纳
参考技术D 逻辑地址就是指理论上的地址,物理地址是指实际上的地址。

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

【中文标题】如何从 Linux 内核模块中的逻辑地址获取物理地址?【英文标题】:How to get the physical address from the logical one in a Linux kernel module? 【发布时间】:2011-09-09 06:32:09 【问题描述】:

除了手动遍历页面目录条目之外,还有什么合适的方法可以通过逻辑地址获取物理地址?我在内核的源代码中寻找了这个功能,发现有一个follow_page 函数可以很好地支持内置的大页面和透明大页面。但它没有导出到内核模块(为什么???)...

所以,我不想发明***,我认为手动重新实现 follow_page 功能并不是很好。

【问题讨论】:

为什么不用mmap()和ioremap()读写物理内存呢?如果这不是你想要的,你能详细说明你的目的吗? 我已经连接了page_fault 处理程序,并尝试在用户页面的分配上进行操作。所以,当异常发生时,我需要确切地知道物理页面地址和大小...... 最简单的答案是没有简单的答案。这是因为用户虚拟地址映射的物理地址的存在/持久性不是给定的;它可以被调出或重新定位,例如随时复制。为了使其“可检查”,必须以某种方式锁定映射,如前所述,例如通过ioremap() 或类似方式,使其永久化。即使您通过 pagedir walk 计算出一个时间点值,您如何确保其他一些内核活动不会立即更改它? 好吧,介绍一下...想象一下,您可以挂钩page_fault 处理程序,并且您的代码的一部分在do_page_fault 之前运行,而另一部分在它之后运行。因此,如您所知,在do_page_fault 之前无法获得#PF,因为中断被禁用。至于刚刚分配的页面在我们仍在异常处理程序中时被调出的可能性,我认为这是非常非常理论的情况,正如您提到的锁定很重要。那么,有了这个假设,有没有一种简单的方法可以将虚拟地址转换为物理地址? 【参考方案1】:

听起来您正在寻找virt_to_phys

【讨论】:

没有。 virt_to_phys 用于内核空间地址,而不是用户空间。 @Ilya:通过阅读您的问题和手册页,我不明白为什么它不起作用。它会给你带来什么? 从描述virt_to_phys函数的内核源代码中,我看到“...返回的物理地址是给定内存地址的物理(CPU)映射。仅使用它才有效对通过 kmalloc 直接映射或分配的地址起作用..." @Ilya:我想我对内存分配不够了解。我知道 kmalloc 可用于分配用户内存,但也许还有其他方法无法使用此功能。不过,这可能值得一试。【参考方案2】:

我认为您可以通过/proc/[pid]/maps(为进程提供虚拟映射)和/proc/[pid]/pagemap(为每个可寻址页面提供虚拟页面到物理页面的映射)的组合,通过间接方法实现虚拟->物理转换.首先,从maps找出你的进程的虚拟地址的映射(这样做是为了你不会搜索pagemap中的每个字节)然后在pagemap中检查所需虚拟地址的物理映射(pagemap是不是文本格式。这里是格式的详细解释Pagemap) 这应该为您提供准确的虚拟-->物理映射

【讨论】:

Hmm.. 页面映射接口似乎不打算在内核中使用。此外,内核文档说:“..pagemap 是内核中的一组新接口(从 2.6.25 开始),它允许用户空间程序通过读取 /proc 中的文件来检查页表和相关信息......”。所以不适合在内核中使用。 @Ilya:好的。即使您获得了一种方法,可以通过该方法在内核中映射虚拟->物理地址,您将如何处理它?对于任何读/写操作,您都只需要使用虚拟地址,因为您无法绕过 MMU。【参考方案3】:

嗯,它可能看起来像这样(从虚拟地址跟随 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);
            
        
    

【讨论】:

您能详细说明一下这段代码吗?它与仅将 follow_page 代码本身复制到模块中有何不同? 没错,它只是follow_page 代码的简化版本。您可以尝试直接调用follow_page 或将其代码复制到模块中。

以上是关于什么是逻辑地址?什么是物理地址的主要内容,如果未能解决你的问题,请参考以下文章

[操作系统]给定一些逻辑地址找到物理地址

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

什么是逻辑设计和物理设计,两者的区别什么?

操作系统--页式段式段页式内存管理的逻辑与物理地址对应关系

物理Dg和逻辑dg的区别

一道操作系统题,在一个分页存储管理系统中,逻辑地址长度为16位,页面大小为4096B,现有逻辑地址2F6AH