【操作系统】一篇文章搞懂虚拟内存管理

引出案例

看下面这段代码,思考为什么会出现这种现象?

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int g_val = 0;
int main()
{
    
    
    pid_t id = fork();
    if (id < 0)
    {
    
    
        perror("fork");
        return 0;
    }
    else if (id == 0)
    {
    
     //child,子进程肯定先跑完,也就是子进程先修改,完成之后,父进程再读取
        g_val = 100;
        printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);
    }
    else
    {
    
     //parent
        sleep(3);
        printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);
    }
    sleep(1);
    return 0;
}

输出结果:

//与环境相关,观察现象即可

child[3046]: 100 : 0x80497e8
parent[3045]: 0 : 0x80497e8

现象:

1.输出地址相同

2.相同地址中存储的数据不同

image.png

谜底:其实这里的地址并不是数据真正的物理地址,而是虚拟地址!!!

虚拟内存管理

  • 现代操作系统普遍采用虚拟内存管理(Virtual Memory Management) 机制,这需要MMU(Memory Management Unit,内存管理单元) 的支持
  • 两个概念:虚拟地址 和 物理地址
  • 如果处理器没有MMU,或者有MMU但没有启用, CPU执行单元发出的内存地址将直接传到芯片引脚上,被内存芯片接收,这称为物理地址(Physical Address)
  • 如果处理器启用了MMU, CPU执行单元发出的内存地址将被MMU截获,从CPU到MMU的地址称为虚拟地址(Virtual Address,以下简称VA) ,而MMU将这个地址翻译成另一个地址发到CPU芯片的外部地址引脚上,也就是将虚拟地址映射成物理地址

image.png

  • 由于有了虚拟内存管理机制,各进程不必担心自己使用的地址范围会不会和别的进程冲突,比如两个进程都使用了相同虚拟地址0x08048000,操作系统可以设置MMU的映射项把它们映射不同的物理地址,它们通过同样的虚拟地址访问不同的物理页面,就不会冲突了。
  • 虚拟内存不具备存储能力,数据依然存储在物理地址中

这就解释了上面引出案例中的现象是什么原因了:父子进程访问的数据分别位于不同的物理地址上,只不过他们的虚拟地址相同而已,通过映射对应不同的物理地址

为什么操作系统不让进程直接访问物理内存,而是弄了一个虚拟地址,来间接访问物理地址呢?

程序运行时,一般需要一块连续的地址,如果没有虚拟地址,直接使用物理地址,会导致空间利用率降低

无虚拟内存时

image.png

此时16M的内存被占用了13M,还剩余3M不连续空间没被利用,还有一个进程需要3M连续空间没法运行

有虚拟内存时

image.png

通过虚拟内存管理,每个程序都认为自己有一块16M大小的内存,通过虚拟内存映射来保证最大化程度利用物理内存,以减少物理内存的浪费

内存管理方式

分段式

在分段式内存管理系统中,进程的虚拟地址段号段内偏移量两部分组成。

  • 虚拟地址 = 短号 + 段内偏移量

为了完成进程虚拟地址到物理地址的映射,处理器会查找内存中的段表,由段号得到段的首地址加上段内偏移量,得到实际的物理地址

  • 物理地址 = 段首地址 + 段内偏移量

这个过程也是由处理器的硬件直接完成的,操作系统只需在进程切换时,将进程段表的首地址装入处理器的特定寄存器当中。这个寄存器一般被称作段表地址寄存器

系统会为每一个进程建立一个映射表

图解

image.png

分页式

  • 将程序的虚拟地址空间划分为固定大小页(page),而物理内存划分为同样大小的页框(page frame)。
  • 程序加载时,可将任意一页放人内存中任意一个页框,这些页框不必连续,从而实现了离散分配
  • 该方法需要CPU的硬件支持,来实现虚拟地址和物理地址之间的映射。
  • 在页式存储管理方式中地址结构由两部构成,前一部分是页号,后一部分为页内偏移量

每个进程有一个页表,描述该进程占用的物理页面及逻辑排列顺序

image.png

址结构由两部构成,前一部分是页号,后一部分为页内偏移量

每个进程有一个页表,描述该进程占用的物理页面及逻辑排列顺序

[外链图片转存中…(img-sGSIo3Vg-1601738271498)]

优点:一个程序不必在物理内存上连续存放,实现了将程序运行所需的内存离散分配在物理内存上

猜你喜欢

转载自blog.csdn.net/weixin_45437022/article/details/108914603