如您所见,有一个简单的C程序粗略地转换为汇编指令。为简单起见,让我们假设每条指令是3字节长,我们假设页面和帧大小也是3字节长。
此过程流正确吗?
程序是否真的分散到页面中,然后像那样放入RAM框架中?
如果是这样,系统如何能够将特定页面与它们所属的特定段相关联?
我在一本操作系统书中读到分段和分页可以共存。此方案是否与此方案相关?
请回答所有这些问题,并尝试澄清有关分段和分页共存的混淆。本课题的参考资料也很好,特别是用C程序编写的一些具体的真实例子,而不是抽象的东西
此流程正确吗? 程序真的分散到页面中,然后像那样放在RAM框架中吗?
原则上:可以。
请注意,部分(";Code";、";data";、";Stack";和";Heap";)只是内存中范围的名称。对于CPU,数据和堆栈之间没有边框。如果是这样,系统如何能够关联特定页面...
我在接下来的几行中简化了很多:
读取内存的工作方式如下:CPU向内存发送一些地址(例如,RAM),它发送数据将被读取的信号。然后,存储器将存储在该地址的数据发送回CPU。
直到20世纪90年代初,还有一些计算机在两个独立的芯片中使用CPU和所谓的MMU。该设备被放置在CPU和内存之间。当CPU向存储器发送地址时,该地址(cpu_address
)实际上被发送到MMU。MMU现在执行与以下C代码操作类似的操作:
int page_table[];
new_address = (page_table[cpu_address / PAGE_SIZE] *
PAGE_SIZE) + (cpu_address % PAGE_SIZE);
.MMU将地址new_address
发送到内存。
MMU的构建方式使操作系统可以写入page_table
。
LOAD R1,[XXX1]
存储在&q;虚拟地址&1234。这意味着:CPU认为指令存储在地址1234。CPU已执行指令STORE [XXX2],5
,并想要执行下一条指令。因此,它必须从内存中读取下一条指令,因此它将地址1234发送到内存。
然而,地址不是由存储器接收的,而是由MMU接收的。MMU现在计算:1234/3 = 411
,1234%3 = 1
。现在,MMU查找页表;假设条目#411是56。然后它计算:56 * 3 + 1 = 169
。它将地址169发送到内存,这样内存将不会返回存储在地址1234中的数据,而会返回存储在地址169中的数据。
现代桌面CPU(但不是小型微控制器)将CPU和MMU放在一个芯片中。
您可能会问:为什么要这样做?
假设一个程序的编译方式是必须将其加载到地址1230,而您的另一个程序也必须加载到地址1230。如果没有MMU,则无法同时加载这两个程序。 使用MMU,操作系统可以将一个程序加载到地址100,而将另一个程序加载到地址200。然后,操作系统将修改page_table
中的数据,其方式是CPU在访问地址1230时访问当前运行的程序。
.到它们所属的特定细分市场?
在编译程序时,链接器决定在哪个地址找到某项(变量或函数)。在最简单的情况下,它只是将第一个函数放到固定地址(例如,始终为1230),并附加所有其他函数和变量。
因此,如果您的程序代码长度为100个字节,则第一个变量位于地址1230+100=1330。
可执行文件(由链接器创建)包含一些信息,说明必须将代码加载到地址1230。
当操作系统加载程序时,它会检查其长度。假设您的程序有120个字节长。它计算120/3=40
,因此需要40页。
page_table
,使地址1230实际访问第一空闲页,1233访问第二空闲页,1236访问第三空闲页,依此类推。
现在操作系统将程序加载到虚拟地址1230-1349(从CPU发送到MMU的地址);由于MMU,数据将写入RAM中的空闲页。
我在一本操作系统书中读到分段和分页可以共存。此方案是否与此方案相关?
在本例中,单词&分段描述了16位和32位x86 CPU的一项特殊功能。至少我不知道有其他的CPU支持这一功能。在现代x86操作系统中,不再使用此功能。您的示例似乎没有使用分段(您的绘图可能会被不同地解释)。
如果在旧的32位Windows版本上运行16位Windows程序(最新版本不再支持16位程序),则同时使用分页和分段。
具体一些用C程序编写的具体实例,而不是抽象的东西
不幸的是,一个具体的真实示例将更加难以理解,因为页面大小远远大于3字节(在x86 CPU上为4千字节)...