什么是逻辑地址?什么是物理地址
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 保护模式下程序执行代码段限长内的偏移地址(假定代码段、数据段如果完全一样)。应用程序员仅需与逻辑地址打交道,而分段和分页机制对您来说是完全透明的,仅由系统编程人员涉及。应用程序员虽然自己可以直接操作内存,那也只能在操作系统给你分配的内存段操作。
线性地址(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
或将其代码复制到模块中。以上是关于什么是逻辑地址?什么是物理地址的主要内容,如果未能解决你的问题,请参考以下文章