📄 1152.html
字号:
<br>
Linux使用请求换页将可执行映象加载到进程的虚拟内存中。当命令执行时,可执行的命令文件被打开,同时其内容被映射到进程的虚拟内存。这些操作是通过修改描叙进程内存映象的数据结构来完成的,此过程称为内存映射。然而只有映象的起始部分被调入物理内存,其余部分仍然留在磁盘上。当映象执行时,它会产生页面错误,这样Linux将决定将磁盘上哪些部分调入内存继续执行。 <br>
<br>
3.1.2 交换 <br>
如果进程需要把一个虚拟页面调入物理内存而正好系统中没有空闲的物理页面,操作系统必须丢弃位于物理内存中的某些页面来为之腾出空间。 <br>
<br>
如果那些从物理内存中丢弃出来的页面来自于磁盘上的可执行文件或者数据文件,并且没有修改过则不需要保存那些页面。当进程再次需要此页面时,直接从可执行文件或者数据文件中读出。 <br>
<br>
但是如果页面被修改过,则操作系统必须保留页面的内容以备再次访问。这种页面被称为dirty页面, 当从内存中移出来时,它们必须保存在叫做交换文件的特殊文件中。相对于处理器和物理内存的速度,访问交换文件的速度是非常缓慢的,操作系统必须在将这些dirty页面写入磁盘和将其继续保留在内存中做出选择。 <br>
<br>
选择丢弃页面的算法经常需要判断哪些页面要丢弃或者交换,如果交换算法效率很低,则会发生"颠簸"现象。在这种情况下,页面不断的被写入磁盘又从磁盘中读回来,这样一来操作系统就无法进行其他任何工作。以图3.1为例,如果物理页面框号1被频繁使用,则页面丢弃算法将其作为交换到硬盘的侯选者是不恰当的。一个进程当前经常使用的页面集合叫做工作集。高效的交换策略能够确保所有进程的工作集保存在物理内存中。 <br>
<br>
Linux使用最近最少使用(LRU)页面衰老算法来公平地选择将要从系统中抛弃的页面。这种策略为系统中的每个页面设置一个年龄,它随页面访问次数而变化。页面被访问的次数越多则页面年龄越年轻;相反则越衰老。年龄较老的页面是待交换页面的最佳侯选者。 <br>
<br>
<br>
<br>
3.1.3 共享虚拟内存 <br>
虚拟内存让多个进程之间可以方便地共享内存。所有的内存访问都是通过每个进程自身的页表进行。对于两个共享同一物理页面的进程,在各自的页表中必须包含有指向这一物理页面框号的页表入口。 <br>
<br>
图3.1中两个进程共享物理页面框号4。对进程X来说其对应的虚拟页面框号为4而进程Y的为6。这个有趣的现象说明:共享物理页面的进程对应此页面的虚拟内存位置可以不同。 <br>
<br>
<br>
<br>
3.1.4 物理与虚拟寻址模式 <br>
操作系统自身也运行在虚拟内存中的意义不大。如果操作系统被迫维护自身的页表那将是一个令人恶心的方案。多数通用处理器同时支持物理寻址和虚拟寻址模式。物理寻址模式无需页表的参与且处理器不会进行任何地址转换。Linux核心直接运行在物理地址空间上。 <br>
<br>
Alpha AXP处理器没有特殊的物理寻址模式。它将内存空间划分为几个区域并将其中两个指定为物理映射地址。核心地址空间被称为KSEG地址空间,它位于地址0xfffffc0000000000以上区域。为了执行位于KSEG的核心代码或访问那里的数据,代码必须在核心模式下执行。Alpha上的Linux核心从地址0xfffffc0000310000开始执行. <br>
<br>
<br>
<br>
3.1.5 访问控制 <br>
页表入口包含了访问控制信息。由于处理器已经将页表入口作为虚拟地址到物理地址的映射,那么可以很方便地使用访问控制信息来判断处理器是否在以其应有的方式来访问内存。 <br>
<br>
诸多因素使得有必要严格控制对内存区域的访问。有些内存,如包含执行代码的部分,显然应该是只读的,操作系统决不能允许进程对此区域的写操作。相反包含数据的页面应该是可写的, 但是去执行这段数据肯定将导致错误发生。多数处理器至少有两种执行方式:核心态与用户态。任何人都不会允许在用户态下执行核心代码或者在用户态下修改核心数据结构。 <br>
<br>
<br>
<br>
<br>
<br>
图3.2 Alpha AXP页表入口 <br>
<br>
<br>
页表入口中的访问控制信息是处理器相关的;图3.2是Alpha AXP处理器的PTE(Page Table Entry)。这些位域的含义如下: <br>
<br>
<br>
V <br>
有效,如果此位置位,表明此PTE有效 <br>
<br>
FOE <br>
“执行时失效”,无论合时只要执行包含在此页面中的指令,处理器都将报告页面错误并将控制传递 <br>
FOW <br>
“写时失效”, 除了页面错误发生在对此页面的写时,其他与上相同。 <br>
FOR <br>
“读时失效”,除了页面错误发生在对此页面的读时,其他与上相同。 <br>
ASM <br>
地址空间匹配。被操作系统用于清洗转换缓冲中的某些入口。 <br>
KRE <br>
运行在核心模式下的代码可以读此页面。 <br>
URE <br>
运行在用户模式下的代码可以读此页面。 <br>
GH <br>
将整个块映射到单个而不是多个转换缓冲时的隐含粒度。 <br>
KWE <br>
运行在核心模式下的代码可以写此页面。 <br>
UWE <br>
运行在用户模式下的代码可以写此页面。 <br>
page frame number <br>
对于V位置位的PTE,此域包含了对应此PTE的物理页面框号;对于无效PTE,此域不为0,它包含了页面在交换文件中位置的信息。 <br>
以下两位由Linux定义并使用。 <br>
<br>
<br>
_PAGE_DIRTY <br>
如果置位,此页面要被写入交换文件。 <br>
_PAGE_ACCESSED <br>
Linux用它表示页面已经被访问过。 <br>
<br>
3.2 高速缓冲 <br>
如果用上述理论模型来实现一个系统,它可能可以工作,但效率不会高。操作系统设计者和处理器设计者都在努力以提高系统的性能。除了制造更快的CPU和内存外,最好的办法是在高速缓冲中维护有用信息和数据以加快某些操作。Linux使用了许多与高速缓冲相关的内存管理策略。 <br>
Buffer Cache <br>
这个buffer cache中包含了被块设备驱动使用的数据缓冲。 <br>
<br>
这些缓冲的单元的大小一般固定(例如说512字节)并且包含从块设备读出或者写入的信息块。块设备是仅能够以固定大小块进行读写操作的设备。所有的硬盘都是块设备。 <br>
<br>
<br>
利用设备标志符和所需块号作索引可以在buffer cache中迅速地找到数据。块设备只能够通过buffer cache来存取。如果数据在buffer cache中可以找到则无需从物理块设备(如硬盘)中读取,这样可以加速访问。 <br>
<br>
Page Cache <br>
<br>
用来加速硬盘上可执行映象文件与数据文件的存取。 <br>
<br>
它每次缓冲一个页面的文件内容。页面从磁盘上读入内存后缓存在page cache中。 <br>
<br>
<br>
<br>
<br>
Swap Cache <br>
只有修改过的页面存储在交换文件中。 <br>
<br>
只要这些页面在写入到交换文件后没有被修改,则下次此页面被交换出内存时,就不必再进行更新写操作,这些页面都可以简单的丢弃。在交换频繁发生的系统中,Swap Cache可以省下很多不必要且耗时的磁盘操作。 <br>
<br>
<br>
<br>
<br>
Hardware Caches <br>
一个常见的hardware cache是处理器中的页表入口cache。处理器不总是直接读取页表而是在需要时缓存页面的转换。这种cache又叫做转换旁视缓冲(Translation Look-aside Buffers),它包含系统中一个或多个处理器的页表入口的缓冲拷贝。 <br>
<br>
<br>
当发出对虚拟地址的引用时,处理器试图找到相匹配的TLB入口。如果找到则直接将虚拟地址转换成物理地址并对数据进行处理。如果没有找到则向操作系统寻求帮助。处理器将向操作系统发出TLB失配信号,它使用一个特定的系统机制来将此异常通知操作系统。操作系统则为此地址匹配对产生新的TLB入口。当操作系统清除此异常时,处理器将再次进行虚拟地址转换。由于此时在TLB中已经有相应的入口,这次操作将成功。 <br>
<br>
<br>
使用高速缓存的缺点在于Linux必须消耗更多的时间和空间来维护这些缓存,并且当缓存系统崩溃时系统也将崩溃。 <br>
<br>
<br>
3.3 Linux 页表 <br>
<br>
<br>
<br>
图3.3 Linux的三级页表结构 <br>
<br>
<br>
Linux总是假定处理器有三级页表。每个页表通过所包含的下级页表的页面框号来访问。图3.3给出了虚拟地址是如何分割成多个域的,每个域提供了某个指定页表的偏移。为了将虚拟地址转换成物理地址
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -