有网友问到我:什么是逻辑地址和物理地址怎么转换针对此问题,我为大家分享了具体的 *** 作 方法 ,希望对你有帮助!
什么是逻辑地址是指由程式产生的和段相关的偏移地址部分。例如,你在进行C语言指针编程中,能读取指针变量本身值(& *** 作),实际上这个值就是逻辑地址,他是相对于你当前进程数据段的地址,不和绝对物理地址相干。只有在Intel实模式下,逻辑地址才和物理地址相等(因为实模式没有分段或分页机制,Cpu不进行自动地址转换);逻辑也就是在Intel保护模式下程式执行代码段限长内的偏移地址(假定代码段、数据段如果完全相同)。应用程式员仅需和逻辑地址打交道,而分段和分页机制对你来说是完全透明的,仅由系统编程人员涉及。应用程式员虽然自己能直接 *** 作内存,那也只能在 *** 作系统 给你分配的内存段 *** 作。
什么是物理地址用于内存芯片级的单元寻址,与处理器和CPU连接的地址总线相对应。 ——这个概念应该是这几个概念中最好理解的一个,但是值得一提的是,虽然可以直接把物理地址理解成插在机器上那根内存本身,把内存看成一个从0字节一直到最大空量逐字节的编号的大数组,然后把这个数组叫做物理地址,但是事实上,这只是一个硬件提供给软件的抽像,内存的寻址方式并不是这样。所以,说它是“与地址总线相对应”,是更贴切一些,不过抛开对物理内存寻址方式的考虑,直接把物理地址与物理的内存一一对应,也是可以接受的。也许错误的理解更利于形而上的抽像。 虚拟内存(virtual memory) 这是对整个内存(不要与机器上插那条对上号)的抽像描述。它是相对于物理内存来讲的,可以直接理解成“不直实的”,“假的”内存,例如,一个0x08000000内存地址,它并不对就物理地址上那个大数组中0x08000000 - 1那个地址元素;之所以是这样,是因为现代 *** 作系统都提供了一种内存管理的抽像,即虚拟内存(virtual memory)。进程使用虚拟内存中的地址,由 *** 作系统协助相关硬件,把它“转换”成真正的物理地址。这个“转换”,是所有问题讨论的关键。有了这样的抽像,一个程序,就可以使用比真实物理地址大得多的地址空间。(拆东墙,补西墙,银行也是这样子做的),甚至多个进程可以使用相同的地址。不奇怪,因为转换后的物理地址并非相同的。 ——可以把连接后的程序反编译看一下,发现连接器已经为程序分配了一个地址,例如,要调用某个函数A,代码不是call A,而是call 0x0811111111 ,也就是说,函数A的地址已经被定下来了。没有这样的“转换”,没有虚拟地址的概念,这样做是根本行不通的。打住了,这个问题再说下去,就收不住了。逻辑地址(logical address) Intel为了兼容,将远古时代的段式内存管理方式保留了下来。逻辑地址指的是机器语言指令中,用来指定一个 *** 作数或者是一条指令的地址。以上例,我们说的连接器为A分配的0x08111111这个地址就是逻辑地址。 ——不过不好意思,这样说,好像又违背了Intel中段式管理中,对逻辑地址要求,“一个逻辑地址,是由一个段标识符加上一个指定段内相对地址的偏移量,表示为 [段标识符:段内偏移量],也就是说,上例中那个0x08111111,应该表示为[A的代码段标识符: 0x08111111],这样,才完整一些” 线性地址(linear address)或也叫虚拟地址(virtual address) 跟逻辑地址类似,它也是一个不真实的地址,如果逻辑地址是对应的硬件平台段式管理转换前地址的话,那么线性地址则对应了硬件页式内存的转换前地址。
逻辑地址和物理地址拓展知识存储器中每一个单元的地址可以用两种方法表示:
1逻辑地址:其表达形式为“段地址:段内偏移地址”。
2物理地址:CPU与存储器进行数据交换时在地址总线上
提供的20位地址信息称为物理地址。
物理地址=段地址×10H+段内偏移量
CPU一次处理的数据是16位,地址总线实际上代表CPU的寻址能力,地址线为20条那么CPU实际的寻址能力就是2的20次方就是1M。实际的物理地址是这样形成的:
段地址10H+偏移地址,偏移地址用IP指向,IP是16位的。
例如段地址是1234H,偏移地址是4321H
那么实际的物理地址怎么算呢:1234H10H+4321H=12340H+4321H=16661H
实际上可以这么来理解,就是段地址左移一位后加上偏移地址就得出实际的物理地址。
这里逻辑地址和物理地址的关系又可以用一个比喻来说明:
比如你的学号是0102,这是你的真实地址亦即物理地址,那么又假如01表示你的班级名称,02表示你相对整个班级的位置,这就是逻辑地址,道理是一样的,只不过在实际由逻辑地址合成物理地址的时候需要将物理地址左移一位,再加上偏移地址。
逻辑地址到物理地址的转换方法以一个例子的形式讲解逻辑地址到物理地址的转换:
某虚拟存储器的用户编程空间共32个页面,每页为1KB,内存为16KB。假定某时刻一用户页表中已调入内存的页面的页号和物理块号的对照表如下:
则逻辑地址0A5C(H)所对应的物理地址是什么要求:写出主要计算过程。
解题过程:
首先要知道页式存储管理的逻辑地址分为两部分:页号和页内地址。物理地址分为两部分:
关系为:逻辑地址= 页号+页内地址d
物理地址= 块号块长度( 等于页面长度 L )+页内地址;
页号: p = lnt( 逻辑地址 A / 页面长度 L ); d = 逻辑地址 A % 页面长度 L (取余)
分析题:已知:用户编程空间共32个页面,2ˆ5 = 32 得知页号部分占5位,由“每页为1KB”,1K=2^10,可知内页地址占10位。
由“内存为16KB”,2^4=16得知块号占4位。
逻辑地址0A5C(H)所对应的二进制表示形式是:0000101001011100,后十位1001011100是页内地址,
00010(本题特例,因为页面长度为1KB)为为页号,页号化为十进制是2,在对照表中找到2对应的物理块号是11,11转换二进制是1011,11 2^10 + d即可求出物理地址为10111001011100,化成十六进制为2 E5C;
即则逻辑地址0A5C(H)所对应的物理地址是2E5C;
1 IP地址和物理地址有什么区别
2 物理地址和逻辑地址的区别
3 虚拟地址与物理地址的概念
4 物理地址什么意思
5 逻辑地址如何转换成物理地址
6 物理地址有什么用
7 物理地址作用是什么
老兄,你的提问有错误呀,数组名说白了就是一个地址,即是一个指针
不知我是否可以这样理解你的提问?“如何在申请数数组时让它的首地址(数组名)为一个指定好的物理地址?”如果我理解的正确的话,感觉几乎是办不到的。首先数组分为静态动态两种,静态的是在编译时分配了一个相对地址。而动态是地址是在堆里面分配的,是运行时进入分配的。即然你要指定的地址是一个固定的物理地址,我感觉你是无法实现的。因为你所指定的地址是在那个区也还不知道呢。
最原始的 *** 作系统是让程序员指定的地址,但现在的 *** 作系统全是使用的相对地址,在程序调入时 *** 作系统为你分配,所以我认为你的想法是不可实现的。其实你这个疑问是概念上的混淆,或者说对指针了解上上的欠缺
首先讲int a[3] = {2,3,4};
这里的a是这个数组的首地址,比如定义如:int p = a;这时如果你进行如下 *** 作:
p++;
printf("%d\n",p);
结果会是输出2,也就是说p+1相当于数组索引加1,但是像你所问的为什么&a和a是相同的 ,首先要知道他们分别代表什么意思,a:像上面所说的是数组的首地址,做自加运算会根据数组类型来计算偏移量,那么&a是什么东西呢,实际上它也是一个指针,是指向一个具有3个元素的数组的指针,如何理解,看以下定义:
如果你定义int q = &a;这时编译器肯定报错,绘制出数据类型不一致,那么你这样样定义就没有问题:int (q)[3] = &a;这时如果你再对q进行++ *** 作,那么加的就不同了,如相面的p++ *** 作后p的值会加4,而这里q++ *** 作后的值会加12,也就是跳过3个数组元素,然而,确实这两个指针的初始值是一样的,只是类型不一样而已,这对二维数组的访问时很方便的,这个你可以参照2维数组得到进一步理解,讲的有点乱,不知道你能不能理解你的二维数组A[0:8,1:5]是这个? 我只见过A[m][n]型的。。。
二维数组其实物理上海市按一位数组存的。
例如A[2][3] 内存中是连续的A[0][0]A[0][1]A[0][2]A[1][0]A[1][1]A[1][2]这样存储的。这是按行存储。 然后知道第一个地址,知道每个数组元素字节。 自己加就行了%p
直接用16进制地址形式输出地址
%d
把地址直接用10进制形式输出
char
a[]
=
"hellow
C++";
int
b[]
=
{0x01,0x02,4,0x08,0};
如上数组如下输出都可以:
printf("十进制地址%d
十六进制地址%p",
a,
a);
printf("十进制地址%d
十六进制地址%p",
b,
b);
printf("十进制地址%d
十六进制地址%p",
&a[0],
&a[0]);
printf("十进制地址%d
十六进制地址%p",
&b[0],
&b[0]);在内核中怎样获得一个结构的物理地址
这样取物理地址是不对的,
物理地址是由硬件规定的,
是固定的。
虚拟地址是有物理地址映射而来,
你不能直接由普通的虚拟地址得到物理地址。
要将数据传到用户空间,
可以直接
做一个
ioctl
调用
,使用
copy_to_user
把数据传过去,
也可以把内核空间的地址映射到用户空间。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)