• C专家编程 第7章 对内存的思考 7.3 虚拟内存


    虚拟内存
    如果它存在,而且你能看见它---它是真实的(real)
    如果他不存在,但你能看见他---它是虚拟的(virtual)
    如果它存在,但你看不见他---它是透明的(transparent)
    如果他不存在,而且你也看不见他---那肯定是你把它擦掉了。

                                                                            ---IBM用于解释虚拟内存的张贴画,大约是在1978年

    虚拟内存的概念,目的就是为了去除这个限制。它的基本思路是用廉价但缓慢的磁盘来扩充快速却昂贵的内存。在任一给定时刻,程序实际需要使用的虚拟内存区段的内容就被载入物理内存中。当物理内存中的数据有一段时间未被使用时,它们就有可能被转移到硬盘中,节省下来的物理内存空间用于载入需要使用的其他数据。除了PC之外(现在的Windows系统也使用了虚拟内存),都使用了虚拟内存。

    多层存储是一个类似的概念,我们可以在一台计算机中到处看到它的存在(如在寄存器和主存中)
    。从理论上说,内存的每个位置都可以用寄存器来代替。虚拟内存只是对多层存储进行扩充,使用磁盘而不是主存来保存运行进程的映像,所以说它们实际上是同一种策略。

    内存媒介的速度与成本关系
    慢速访问                       <--------                        快速访问
    磁带        磁盘        内存        cache寄存器              CPU寄存器
    成本低,容量大                                               成本高,容量小

    SunOS中的进程执行于32位地址空间。操作系统负责具体细节,使每个进程都以为自己拥有整个地址空间的独家访问权。这个幻觉是通过“虚拟内存”实现的。所有进程共享机器的物理内存,当内存用完时就用磁盘保存数据。在进程运行时,数据在磁盘和内存之间来回移动。
    内存管理硬件负责把虚拟地址翻译成物理地址,并让一个进程始终运行于系统的真正的内存中。应用程序程序员只看到虚拟地址,并不知道自己的进程在磁盘和内存之间来回切换,除非他们观察运行时间或者使用诸如ps之类的系统命令。
                                                                              CPU
                                    4GB                                      ^ 
    进程虚拟地址空间                                                 | 
                                                                                                      ------>物理地址(几GB) 
                                                   虚拟地址<------ 内存管理单元     ------>物理地址(几十MB)     
    系统中的每个进程                                            (MMU) 
    都有自己的地址空间   
                                      0 

    虚拟地址通过页的形式组织。页就是操作系统在磁盘和内存之间移来移去或进行保护的单位,一般为几KB。可以通过/usr/ucb/pagesize来观察你的系统中的页面大小。当内存的映像在磁盘和物理内存间来回移动时,称它们是page in(移入内存)或page out(移到磁盘)。

    从潜在的可能性上说,与进程有关的所有内存都将被系统所使用。如果该进程可能不会马上运行(比如它的优先级低,也可能是它处于睡眠状态),操作系统可以暂时取回所有分配给它的物理内存资源,将该进程的所有相关信息都被备份到磁盘上。这样,这个进程就被“换出”。在磁盘中有一个特殊的“交换区”,用于保存从内存中换出的进程。在一台机器中,交换区的大小一般是物理内存的几倍。只有用户进程才会被换进换出,SunOS内核常驻于内存中。

    进程只能操作位于物理内存中的页面。当进程引用一个不在物理内存中,内存管理单元(MMU)
    就会产生一个页错误。内核对此事件作出反应,并判断该引用是否有效。如果无效,那么内核向进程发出一个“segmentation violation”(段违规)的信号。如果有效,内核就从磁盘取回该页,换入到内存中。一旦页面进入内存,进程便被解锁,可以重新运行---进程并不知道它曾经因为页面换入事件等待了一会儿。

    SunOS对于磁盘的文件系统和主存有一种统一的观点。操作系统使用相同的底层数据结(vnode,
    或称为“虚拟结点”)来操纵这两者。所有的虚拟内存操作都处于同样的设计哲学,就是把文件区域映射到内存区域中。这可以提高性能,并允许客观的代码复用。你可能听说过“hat layer”(帽子层)---这就是驱动MMU的“硬件地址翻译”软件。它极度依赖硬件,每出现一个新的计算机架构,它都必须重新改写。

    虚拟内存技术已成为操作系统中一项不可或缺的技术,它允许多个进程运行于较小的物理内存中。 

    /*你可以分配多大的内存*/

    #include
    #include

    int main() {
        int MB = 0;
        while (malloc(1 << 20)) ++MB;
        printf("Allocated %d MB total\n", MB);
        return 0;} 
    /* 输出: 

    */ 

    /*总共分配的内存量取决于交换区和你的系统配置中的进程限制。
     *为了让这个程序能够在内存限制的MS-DOS上运行,把每次分配的单元从
     *1MB改为1KB(就是把1<<20改为1<<10,并用KB代替MB)。
     */

  • 相关阅读:
    【前端】移动互联动画
    网络协议从入门到底层原理学习(三)—— 路由
    还在为学不会JVM&G1烦恼吗?看阿里P8源码分析笔记,你想要的都有
    python循环判断
    Visual Studio 2022配置PCL1.12.1版本点云库
    【感恩系列】:说点事儿 以及 我把所有的粉丝放到了中国地图上啦~
    ffmpeg2段视频合成一段
    深入剖析@ConfigurationProperties注解
    Notion的安装与使用
    学js的第二十一天
  • 原文地址:https://blog.csdn.net/weixin_40186813/article/details/126081518