物理地址逻辑地址虚拟地址的概念

合集下载

内存寻址的三种模式

内存寻址的三种模式

内存寻址的三种模型1. 地址的种类首先明确一下逻辑地址和线性地址这两个概念:1. 逻辑地址2. 线性地址3. 物理地址1.1 逻辑地址:逻辑地址是编译器生成的,我们使用在linux环境下,使用C语言指针时,指针的值就是逻辑地址。

对于每个进程而言,他们都有一样的进程地址空间,类似的逻辑地址,甚至很可能相同。

1.2 线性地址:线性地址是由分段机制将逻辑地址转化而来的,如果没有分段机制作用,那么程序的逻辑地址就是线性地址了。

1.3 物理地址物理地址是CPU在地址总线上发出的电平信号,要得到物理地址,必须要将逻辑地址经过分段,分页等机制转化而来。

2. 三种寻址模型x86体系结构下,使用的较多的内存寻址模型主要有三种:1. 实模式扁平模型real mode flat model2. 实模式分段模型real mode segment model3. 保护模式扁平模型protected mode flat model下面是对这三种模型的描述实模式和保护模式相对,实模式运行于20位地址总线,保护模式则启用了32位地址总线,地址使用的是虚拟地址,引入了描述符表;虽然二者都引入了段这样一个概念,但是实模式的段是64KB固定大小,只有16KB个不同的段,CS,DS等存储的是段的序号(想想为什么?)。

保护模式则引入了GDT和LDT段描述符表的数据结构来定义每个段。

扁平模型和分段模型相对,区别在于程序的线性地址是共享一个地址空间还是需要分成多个段,即为多个程序同时运行在同一个CS,DS的范围内还是每个程序都拥有自己的CS,DS:前者(flat)指令的逻辑地址要形成线性地址,不需要切换CS,DS;后者的逻辑地址,必须要经过段选择子去查找段描述符,切换CS,DS,才能形成线性地址。

3. 实模式扁平模型该模式只有在386及更高的处理器中才能出现!80386的实模式,就是指CPU可用的地址线只有20位,能寻址0~1MB的地址空间。

操作系统-存储管理(4)段页式虚拟存储

操作系统-存储管理(4)段页式虚拟存储

操作系统-存储管理(4)段页式虚拟存储物理地址:⼜称绝对地址,即程序执⾏所使⽤的地址空间(处理器执⾏指令时按照物理地址进⾏)逻辑地址:⼜称相对地址,即⽤户编程所使⽤的地址空间,从0开始编号,有两种形式:⼀维逻辑地址(地址)⼆维逻辑地址(段号:段内地址)主存储器空间的分配与去配:分配:进程装⼊主存时,存储管理软件进⾏具体的主存分配操作,并设置⼀个表格记录主存空间的分配情况去配:当某个进程撤离或主动归还主存资源时,存储管理软件要收回它所占⽤的全部或者部分存储空间,调整主存分配表信息主存储器空间的共享:多个进程共享主存储器资源:多道程序设计技术使若⼲个程序同时进⼊主存储器,各⾃占⽤⼀定数量的存储空间,共同使⽤⼀个主存储器多个进程共享主存储器的某些区域:若⼲个协作进程有共同的主存程序块或者主存数据块多道程序设计需要复⽤主存:按照分区复⽤:主存划分为多个固定/可变尺⼨的分区,⼀个程序/程序段占⽤⼀个分区按照页架复⽤:主存划分成多个固定⼤⼩的页架,⼀个程序/程序段占⽤多个页架装载程序/加载器(loader)把可执⾏程序装⼊内存的⽅式有:绝对装载可重定位装载动态运⾏时装载地址转换:⼜称重定位,即把可执⾏程序逻辑地址转换成绝对地址,可分为:静态地址重定位:由装载程序实现装载代码模块的加载和地址转换(⽆需硬件⽀持),把它装⼊分配给进程的内存指定区域,其中所有指令代码和数据的逻辑地址在执⾏前⼀次全部修改为内存物理地址。

早期单任务单⽤户OS使⽤。

动态地址重地位:由装载程序实现装载代码模块的加载,把它装⼊进程的内存在指定区域,但对链接程序处理过的应⽤程序逻辑地址不做修改,程序内存起始地址被置⼊重定位寄存器(基址寄存器)。

程序执⾏过程中每当CPU访问程序和数据引⽤内存地址时,由硬件地址转换机构截取此逻辑地址并加上重定位寄存器的值。

运⾏时链接地址重定位存储保护:为避免主存中的多个进程相互⼲扰,必须对主存中的程序和数据进⾏保护。

cortex m3对存储器的寻址空间

cortex m3对存储器的寻址空间

cortex m3对存储器的寻址空间Cortex-M3是一款基于ARM Cortex-M内核的32位微控制器,它在嵌入式系统中广泛应用于各种应用领域。

在Cortex-M3中,存储器的寻址空间是非常重要的,它决定了系统能够访问的存储器范围以及存储器的布局方式。

本文将围绕Cortex-M3的存储器寻址空间展开讨论。

Cortex-M3的存储器寻址空间可以分为两个部分:内存和外设。

我们来看内存寻址空间。

Cortex-M3支持32位的地址总线,因此它能够寻址的内存空间为2^32,即4GB。

然而,实际上,Cortex-M3并不一定具备这么大的内存容量,因为内存的具体大小取决于具体的微控制器型号和所选用的存储器配置。

一般来说,Cortex-M3的内存容量可以从几KB到几MB不等。

内存空间通常被划分为多个片段,例如代码段、数据段和堆栈段,以便于程序的执行和数据的存储。

Cortex-M3的内存寻址空间还可以进一步划分为两个部分:SRAM 和Flash。

SRAM(静态随机存取存储器)用于存储程序的数据和临时变量,它具有快速的读写速度和低功耗的特点。

Flash(闪存)用于存储程序的代码和数据,它具有非易失性和较大的存储容量。

在Cortex-M3中,SRAM和Flash的大小和位置可以根据具体的应用需求进行配置。

除了内存空间,Cortex-M3还具有外设寻址空间。

外设是指与微控制器相连的各种外部设备,例如串口、I2C总线和GPIO等。

Cortex-M3通过外设寄存器与外设进行通信和控制。

外设寄存器位于特定的地址空间中,通过访问这些寄存器,可以对外设进行配置和操作。

不同的外设具有不同的地址分配,这样就能够实现对各个外设的独立控制。

在Cortex-M3中,存储器的寻址方式有两种:物理地址和逻辑地址。

物理地址是指存储器芯片上的实际地址,逻辑地址则是指程序中使用的虚拟地址。

物理地址和逻辑地址之间的转换是通过存储管理单元(MMU)来实现的。

逻辑地址与物理地址

逻辑地址与物理地址

逻辑地址与物理地址物理地址是外部连接使用的、唯一的,它是“与地址总线相对应”;而逻辑地址是内部和编程使用的、并不唯一。

在内存中的实际地址就是所谓的“物理地址”,而逻辑地址就是逻辑段管理内存而形成的。

例如,你在进行C语言指针编程中,可以读取指针变量本身值(&操作),实际上这个值就是逻辑地址,它是相对于你当前进程数据段的地址(偏移地址),不和绝对物理地址相干。

只有在Intel实模式下,逻辑地址才和物理地址相等(因为实模式没有分段或分页机制,Cpu不进行自动地址转换),逻辑地址也就是在Intel 保护模式下程序执行代码段限长内的偏移地址(假定代码段、数据段如果完全一样)。

8086体系的CPU一开始是20根地址线, 寻址寄存器是16位, 16位的寄存器可以访问64K的地址空间, 如果程序要想访问大于64K的内存, 就要把内存分段, 每段64K, 用段地址+偏移量的方法来访问。

386CPU出来之后, 采用了32条地址线, 地址寄存器也扩为32位, 这样就可以不用分段了, 直接用一个地址寄存器来线性访问4G的内存了. 这就叫平面模式.将逻辑地址中的段地址左移4位,加上偏移地址就得到20位物理地址。

这里左移的4位是二进制位;如果用十六进制表达地址就是左移一位。

左移4位还可以表达为乘以16,即:段地址×16+偏移地址。

同一个物理地址可以对应多个逻辑地址形式。

所以物理地址转换为逻辑地址,需要明确段基地址或偏移地址,然后同上原则确定另一个地址。

逻辑地址1460H : 0100H 或1380H : 0900H物理地址14700H于是,对于主存14700H单元,我们可以描述为在1460H(或1380H)段的0100H(或0900H)单元,或者说主存1460H : 0100H(或1380H : 0900H)单元。

存储单元的地址可以用段基值和段内偏移量来表示,段基值确定它所在的段居于整个存储空间的位置,偏移量确定它在段内的位置,这种地址表示方式称为逻辑地址。

什么是物理地址 逻辑地址

什么是物理地址 逻辑地址

什么是物理地址逻辑地址网络中的地址分为物理地址和逻辑地址两类,与网络层的IP地址传输层的端口号以及应用层的用户名相比较,局域望网的MAC层地址是由硬件来处理的,叫做物理地址或硬件地址.IP地址传输层的端口号以及应用层的用户名是逻辑地址一由软件处理.我认为你说的MAC地址应该就是物理地址.大多数局域网通过为网卡分配一个硬件地址来标识一个联网的计算机或其他设备.所谓物理地址是指固化在网卡EPROM中的地址,这个地址应该保证在全网是唯一的.IEEE注册委员会为每一个生产厂商分配物理地址的前三字节,即公司标识.后面三字节由厂商自行分配.即一个厂商获得一个前三字节的地址可以生产的网卡数量是16777216块.即一块网卡对应一个物理地址.也就是说对应物理地址的前三字节可以知道他的生产厂商.如果固化在网卡中的地址为002514895423,那么这块网卡插到主机A中,主机A的地址就是002514895423,不管主机A是连接在局域网1上还是在局域网2上,也不管这台计算机移到什么位置,主机A的物理地址就是002514895423 .它是不变的,而且不会和世界上任何一台计算机相同.当主机A发送一帧时,网卡执行发送程序时,直接将这个地址作为源地址写入该帧.当主机A接收一帧时,直接将这个地址与接收帧目的地址比较,以决定是否接收.物理地址MAC(Media Access Control, 介质访问控制)地址是识别LAN(局域网)节点的标识。

网卡的物理地址通常是由网卡生产厂家烧入网卡的EPROM(一种闪存芯片,通常可以通过程序擦写),它存储的是传输数据时真正赖以标识发出数据的电脑和接收数据的主机的地址。

也就是说,在网络底层的物理传输过程中,是通过物理地址来识别主机的,它一般也是全球唯一的。

比如,著名的以太网卡,其物理地址是48bit(比特位)的整数,如:44-45-53-54-00-00,以机器可读的方式存入主机接口中。

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

CC++进程间通信内存共享

CC++进程间通信内存共享

CC++进程间通信内存共享介绍内存共享前,说下之前的误区,觉得,可以⽤指针来在⽗⼦进程中传递数据,其实,在fork()后,⽗⼦进程的地址空间是相互独⽴的!所以在⽗⼦进程间传递指针是没有意义的。

这⾥就涉及到物理地址和逻辑地址(或称虚拟地址)的概念。

从逻辑地址到物理地址的映射称为地址重定向。

分为:静态重定向--在程序装⼊主存时已经完成了逻辑地址到物理地址和变换,在程序执⾏期间不会再发⽣改变。

动态重定向--程序执⾏期间完成,其实现依赖于硬件地址变换机构,如基址寄存器。

逻辑地址:CPU所⽣成的地址。

CPU产⽣的逻辑地址被分为 :p (页号)它包含每个页在物理内存中的基址,⽤来作为页表的索引;d (页偏移),同基址相结合,⽤来确定送⼊内存设备的物理内存地址。

物理地址:内存单元所看到的地址。

⽤户程序看不见真正的物理地址。

⽤户只⽣成逻辑地址,且认为进程的地址空间为0到max。

物理地址范围从R+0到R+max,R为基地址,地址映射-将程序地址空间中使⽤的逻辑地址变换成内存中的物理地址的过程。

由内存管理单元(MMU)来完成。

fork()会产⽣⼀个和⽗进程完全相同的⼦进程,但⼦进程在此后多会exec系统调⽤,出于效率考虑,linux中引⼊了“写时复制“技术,也就是只有进程空间的各段的内容要发⽣变化时,才会将⽗进程的内容复制⼀份给⼦进程。

在fork之后exec之前两个进程⽤的是相同的物理空间(内存区),⼦进程的代码段、数据段、堆栈都是指向⽗进程的物理空间,也就是说,两者的虚拟空间不同,但其对应的物理空间是同⼀个。

当⽗⼦进程中有更改相应段的⾏为发⽣时,再为⼦进程相应的段分配物理空间,如果不是因为exec,内核会给⼦进程的数据段、堆栈段分配相应的物理空间(⾄此两者有各⾃的进程空间,互不影响),⽽代码段继续共享⽗进程的物理空间(两者的代码完全相同)。

⽽如果是因为exec,由于两者执⾏的代码不同,⼦进程的代码段也会分配单独的物理空间。

请问什么是逻辑地址

请问什么是逻辑地址1、请问什么是逻辑地址?什么是物理地址?答:逻辑地址:在计算机中,访内指令给出的地址(操作数)叫逻辑地址,也叫相对地址。

逻辑地址由两个16位的地址分量构成,一个为段基值,另一个为偏移地址。

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

物理地址=段基值×10H+偏移地址2、CPU与外设交换信息的方式有哪几种?答:CPU与外设通过接口交换信息的控制方式有:程序控制方式、中断控制方式、直接存储器存取方式(DMA方式)和输入/输出处理机方式。

程序控制方式:无条件传送控制方式、条件传送控制方式3、一个中断过程包括哪些环节?答:一个中断过程应该包含以下五个过程:(1)中断请求;(2)中断排队;(3)中断响应;(4)中断服务;(5)中断返回。

(1)中断请求当中断源有请求时,将中断请求触发器置1:* 若中断屏蔽触发器为“0”状态,表示允许该中断源向CPU发出中断请求“信号”;* 若中断屏蔽触发器为“1”状态,表示禁止该中断源向CPU发出中断请求“信号”。

尽管该中断源有中断请求,也不能被送出,称该中断请求被屏蔽了。

(2)中断排队和(3)中断响应CPU通过中断排队确定了要响应的中断源后,进入中断响应,自动完成以下步骤:①关中断;②保护断点,将正在执行的程序地址(断点)入栈;③保护现场,标志寄存器FR自动入栈;④形成中断服务程序入口地址。

(4)中断服务和(5)中断返回中断服务是指CPU执行中断服务程序。

中断服务程序应包括:①保护现场,CPU响应中断时自动保护断点,寄存器则由程序员决定是否要入栈;②开中断,CPU响应中断时,自动执行关中断操作。

要实现中断嵌套,必须在中断服务程序中开中断;③中断处理,对中断源作相应的处理,是中断服务程序的核心;④关中断,若中断服务程序设置了开中断,则此时应该关中断,以保证恢复现场的操作不被打断;⑤恢复现场,按后进先出的原则,PUSH和POP应配对使用;⑥中断返回,从堆栈中弹出断点,返回主程序。

通俗理解物理地址、逻辑地址、线性地址、虚拟地址、有效地址的区别

通俗理解物理地址、逻辑地址、线性地址、虚拟地址、有效地址
的区别
物理地址:物理地址就是内存单元的绝对地址,⽐如你有⼀个4G的内存条插在电脑上,物理地址0x0000就表⽰内存条的第⼀个存储单元,0x0010就表⽰内存条的第17个存储单元,不管CPU内部怎么处理地址,最终访问的都是物理地址。

在CPU实模式下“段基址+段内偏移地址”就是物理地
址,CPU可以使⽤此地址直接访问内存。

线性地址、虚拟地址:CPU在保护模式下,“段基址+段内偏移地址”叫做线性地址,注意,保护模式下段基址寄存器中存储的不是真正的段基值(和实模式的含义不⼀样),⽽是被称为“段选择⼦”的东西,通过段选择⼦在GDT(全局描述表)中找到真正的段基值。

另外,如果CPU在保护模式下没有开启分页功能,则线性地址就被当做最终的物理地址来⽤,若开启了分页功能,则线性地址就叫虚拟地址(在没开启分页功能的情况下线性地址和虚拟地址就是⼀回事)。

但是,如果开启分页功能,虚拟地址(或线性地址)还要通过页部件电路转换成最终的物理地址。

逻辑地址、有效地址:⽆论CPU在什么模式下,段内偏移地址⼜称为有效地址或者逻辑地址(只是叫法不⼀样罢了),例如实模式下 “mov ax,
[0x7c00]”,0x7c00就是逻辑地址(或有效地址),但这条指令最终操作的物理地址是DS*16+0x7c00。

物理地址的含义

物理地址的含义物理地址是什么?物理地址的含义是什么? 小编整理了物理地址的相关资料,下面大家跟着小编一起去了解一下吧。

物理地址的含义MAC地址也叫物理地址、硬件地址或链路地址,由网络设备制造商生产时写在硬件内部。

IP地址与MAC地址在计算机里都是以二进制表示的,IP地址是32 位的,而MAC地址则是48位的。

MAC 地址的长度为48位(6个字节),通常表示为12个16进制数,每2个16进制数之间用冒号隔开,如:08: 00:20:0A:8C:6D就是一个MAC地址,其中前6位16进制数08:00:20代表网络硬件制造商的编号,它由IEEE(电气与电子工程师协会)分配,而后3位16进制数0A:8C:6D代表该制造商所制造的某个网络产品(如网卡)的系列号。

只要你不去更改自己的MAC地址,那么你的MAC地址在世界是惟一。

静态IP:在Internet上有千百万台主机,为了区分这些主机,人们给每台主机都分配了一个专门的地址,称为IP地址。

通过IP地址就可以访问到每一台主机。

IP地址由4部分数字组成,每部分数字对应于8位二进制数字,各部分之间用小数点分开。

如某一台主机的IP地址为:211.152.65.112 ,Internet IP地址由NIC(Internet Network Information Center)统一负责全球地址的规划、管理;同时由Inter NIC、APNIC、RIPE三大网络信息中心具体负责美国及其它地区的IP地址分配。

固定IP:固定IP地址是长期固定分配给一台计算机使用的IP 地址,一般是特殊的服务器才拥有固定IP地址。

动态IP:因为IP地址资源非常短缺,通过电话拨号上网或普通宽带上网用户一般不具备固定IP地址,而是由ISP动态分配暂时的一个IP地址。

普通人一般不需要去了解动态IP地址,这些都是计算机系统自动完成的。

公有地址(Public address)由Inter NIC(Internet Network Information Center 因特网信息中心)负责。

总线地址、物理地址、虚拟地址相关概念澄清

总线地址、物理地址、虚拟地址相关概念澄清Now, on normal PCs the bus address is exactly the same as the physicaladdress, and things are very simple indeed. However, they are that simplebecause the memory and the devices share the same address space, and that isnot generally necessarily true on other PCI/ISA setups.Now, just as an example, on the PReP (PowerPC Reference Platform), theCPU sees a memory map something like this (this is from memory):0-2 GB "real memory"2 GB-3 GB "system IO" (inb/out and similar accesses on x86)3 GB-4 GB "IO memory" (shared memory over the IO bus)Now, that looks simple enough. However, when you look at the same thing fromthe viewpoint of the devices, you have the reverse, and the physical memoryaddress 0 actually shows up as address 2 GB for any IO master.So when the CPU wants any bus master to write to physical memory 0, it has to give the master address 0x80000000 as the memory address.So, for example, depending on how the kernel is actually mapped on the PPC, you can end up with a setup like this: physical address: 0virtual address: 0xC0000000bus address: 0x80000000where all the addresses actually point to the same thing. It's just seen through different translations..Similarly, on the Alpha, the normal translation isphysical address: 0virtual address: 0xfffffc0000000000bus address: 0x40000000(but there are also Alphas where the physical address and the bus address are the same).Anyway, the way to look up all these translations, you do#include <asm/io.h>phys_addr = virt_to_phys(virt_addr);virt_addr = phys_to_virt(phys_addr);bus_addr = virt_to_bus(virt_addr);virt_addr = bus_to_virt(bus_addr);Now, when do you need these?there are actually _three_ different ways of lookingat memory addresses, and in this case we actually want the third, the so-called "bus address".Essentially, the three ways of addressing memory are (this is "real memory",that is, normal RAM--see later about other details):- CPU untranslated. This is the "physical" address. Physical address 0 is what the CPU sees when it drives zeroes on the memory bus.- CPU translated address. This is the "virtual" address, and is completely internal to the CPU itself with the CPU doing the appropriate translations into "CPU untranslated".- bus address. This is the address of memory as seen by OTHER devices, not the CPU. Now, in theory there could be many different bus addresses, with each device seeing memory in some device-specific way, but happilymost hardware designers aren't actually actively trying to make things any more complex than necessary, so you can assume that all external hardware sees the memory the same way.You want the _virtual_ address when you are actually going to access that pointer from the kernel. So you can have something like this:/** this is the hardware "mailbox" we use to communicate with* the controller. The controller sees this directly.*/struct mailbox {__u32 status;__u32 bufstart;__u32 buflen;..} mbox;unsigned char * retbuffer;/* get the address from the controller */retbuffer = bus_to_virt(mbox.bufstart);switch (retbuffer[0]) {case STATUS_OK:...on the other hand, you want the bus address when you have a buffer that you want to give to the controller: /* ask the controller to read the sense status into "sense_buffer" */mbox.bufstart = virt_to_bus(&sense_buffer);mbox.buflen = sizeof(sense_buffer);mbox.status = 0;notify_controller(&mbox);And you generally _never_ want to use the physical address, because you can't use that from the CPU (the CPU only uses translated virtual addresses), and you can't use it from the bus master.So why do we care about the physical address at all? We do need the physical address in some cases, it's just not very often in normal code. The physical address is needed if you use memory mappings, for example, because the "remap_page_range()" mm function wants the physical address of the memory to be remapped.This memory is called "PCI memory" or "shared memory" or "IO memory" or whatever, and there is only one way to access it: the readb/writeb and related functions. You should never take the address of such memory, because there is really nothing you can do with such an address: it's not conceptually in the same memory space as "real memory" at all, so you cannot just dereference a pointer.物理地址与总线地址1)物理地址是与CPU相关的。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、概念物理地址(physical address)用于内存芯片级的单元寻址,与处理器和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)跟逻辑地址类似,它也是一个不真实的地址,如果逻辑地址是对应的硬件平台段式管理转换前地址的话,那么线性地址则对应了硬件页式内存的转换前地址。

-------------------------------------------------------------CPU将一个虚拟内存空间中的地址转换为物理地址,需要进行两步:首先将给定一个逻辑地址(其实是段内偏移量,这个一定要理解!!!),CPU要利用其段式内存管理单元,先将为个逻辑地址转换成一个线程地址,再利用其页式内存管理单元,转换为最终物理地址。

这样做两次转换,的确是非常麻烦而且没有必要的,因为直接可以把线性地址抽像给进程。

之所以这样冗余,Intel完全是为了兼容而已。

2、CPU段式内存管理,逻辑地址如何转换为线性地址一个逻辑地址由两部份组成,段标识符: 段内偏移量。

段标识符是由一个16位长的字段组成,称为段选择符。

其中前13位是一个索引号。

后面3位包含一些硬件细节,如图:最后两位涉及权限检查,本贴中不包含。

索引号,或者直接理解成数组下标——那它总要对应一个数组吧,它又是什么东东的索引呢?这个东东就是“段描述符(segment descriptor)”,呵呵,段描述符具体地址描述了一个段(对于“段”这个字眼的理解,我是把它想像成,拿了一把刀,把虚拟内存,砍成若干的截——段)。

这样,很多个段描述符,就组了一个数组,叫“段描述符表”,这样,可以通过段标识符的前13位,直接在段描述符表中找到一个具体的段描述符,这个描述符就描述了一个段,我刚才对段的抽像不太准确,因为看看描述符里面究竟有什么东东——也就是它究竟是如何描述的,就理解段究竟有什么东东了,每一个段描述符由8个字节组成,如下图:这些东东很复杂,虽然可以利用一个数据结构来定义它,不过,我这里只关心一样,就是Base字段,它描述了一个段的开始位置的线性地址。

Intel设计的本意是,一些全局的段描述符,就放在“全局段描述符表(GDT)”中,一些局部的,例如每个进程自己的,就放在所谓的“局部段描述符表(LDT)”中。

那究竟什么时候该用GDT,什么时候该用LDT呢?这是由段选择符中的T1字段表示的,=0,表示用GDT,=1表示用LDT。

GDT在内存中的地址和大小存放在CPU的gdtr控制寄存器中,而LDT则在ldtr寄存器中。

好多概念,像绕口令一样。

这张图看起来要直观些:首先,给定一个完整的逻辑地址[段选择符:段内偏移地址],1、看段选择符的T1=0还是1,知道当前要转换是GDT中的段,还是LDT中的段,再根据相应寄存器,得到其地址和大小。

我们就有了一个数组了。

2、拿出段选择符中前13位,可以在这个数组中,查找到对应的段描述符,这样,它了Base,即基地址就知道了。

3、把Base + offset,就是要转换的线性地址了。

还是挺简单的,对于软件来讲,原则上就需要把硬件转换所需的信息准备好,就可以让硬件来完成这个转换了。

OK,来看看Linux怎么做的。

3、Linux的段式管理Intel要求两次转换,这样虽说是兼容了,但是却是很冗余,呵呵,没办法,硬件要求这样做了,软件就只能照办,怎么着也得形式主义一样。

另一方面,其它某些硬件平台,没有二次转换的概念,Linux也需要提供一个高层抽像,来提供一个统一的界面。

所以,Linux的段式管理,事实上只是“哄骗”了一下硬件而已。

按照Intel的本意,全局的用GDT,每个进程自己的用LDT——不过Linux则对所有的进程都使用了相同的段来对指令和数据寻址。

即用户数据段,用户代码段,对应的,内核中的是内核数据段和内核代码段。

这样做没有什么奇怪的,本来就是走形式嘛,像我们写年终总结一样。

include/asm-i386/segment.h[Copy to clipboard][ - ] CODE:#define GDT_ENTRY_DEFAULT_USER_CS 14#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS * 8 + 3)#define GDT_ENTRY_DEFAULT_USER_DS 15#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS * 8 + 3)#define GDT_ENTRY_KERNEL_BASE 12#define GDT_ENTRY_KERNEL_CS (GDT_ENTRY_KERNEL_BASE + 0)#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS * 8)#define GDT_ENTRY_KERNEL_DS (GDT_ENTRY_KERNEL_BASE + 1)#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS * 8)把其中的宏替换成数值,则为:[Copy to clipboard][ - ] CODE:#define __USER_CS 115 [00000000 1110 0 11]#define __USER_DS 123 [00000000 1111 0 11]#define __KERNEL_CS 96 [00000000 1100 0 00]#define __KERNEL_DS 104 [00000000 1101 0 00]方括号后是这四个段选择符的16位二制表示,它们的索引号和T1字段值也可以算出来了[Copy to clipboard][ - ] CODE:__USER_CS index= 14 T1=0__USER_DS index= 15 T1=0__KERNEL_CS index= 12 T1=0__KERNEL_DS index= 13 T1=0T1均为0,则表示都使用了GDT,再来看初始化GDT的内容中相应的12-15项(arch/i386/head.S):[Copy to clipboard][ - ] CODE:.quad 0x00cf9a000000ffff /* 0x60 kernel 4GB code at 0x00000000 */.quad 0x00cf92000000ffff /* 0x68 kernel 4GB data at 0x00000000 */.quad 0x00cffa000000ffff /* 0x73 user 4GB code at 0x00000000 */.quad 0x00cff2000000ffff /* 0x7b user 4GB data at 0x00000000 */按照前面段描述符表中的描述,可以把它们展开,发现其16-31位全为0,即四个段的基地址全为0。

这样,给定一个段内偏移地址,按照前面转换公式,0 + 段内偏移,转换为线性地址,可以得出重要的结论,“在Linux 下,逻辑地址与线性地址总是一致(是一致,不是有些人说的相同)的,即逻辑地址的偏移量字段的值与线性地址的值总是相同的。

!!!”忽略了太多的细节,例如段的权限检查。

呵呵。

Linux中,绝大部份进程并不例用LDT,除非使用Wine ,仿真Windows程序的时候。

4.CPU的页式内存管理CPU的页式内存管理单元,负责把一个线性地址,最终翻译为一个物理地址。

从管理和效率的角度出发,线性地址被分为以固定长度为单位的组,称为页(page),例如一个32位的机器,线性地址最大可为4G,可以用4KB为一个页来划分,这页,整个线性地址就被划分为一个tatol_page[2^20]的大数组,共有2的20个次方个页。

这个大数组我们称之为页目录。

目录中的每一个目录项,就是一个地址——对应的页的地址。

另一类“页”,我们称之为物理页,或者是页框、页桢的。

是分页单元把所有的物理内存也划分为固定长度的管理单位,它的长度一般与内存页是一一对应的。

这里注意到,这个total_page数组有2^20个成员,每个成员是一个地址(32位机,一个地址也就是4字节),那么要单单要表示这么一个数组,就要占去4MB的内存空间。

相关文档
最新文档