0
点赞
收藏
分享

微信扫一扫

Linux 物理内存、虚拟内存


Linux 物理内存、虚拟内存_linux

电脑里内存分内存条(这里我们叫物理内存)和硬盘,内存条保存程序运行时数据,也称为物理内存,硬盘持久保存数据。

在进程的执行过程当中,Linux会根据内核需要,分配一片内存区域,进程会将这片区域当成工作区。然后按照要求去执行这些操作。

那么虚拟内存是什么?

程序运行会启动一个进程,进程里有程序段、全局数据、栈和堆,这些都会加载到内存里,每一部分都有对应的内存地址,进程就是一直在处理这些地址中数据。

然而在Linux下,进程不能直接读写物理内存地址(它不能直接读取内存条对应的地址)。进程中能访问的地址,只能是虚拟内存地址(virtual memory address)。操作系统会把虚拟内存地址翻译成真实的内存地址。这种内存管理方式,称为虚拟内存(virtual memory)。

物理内存和虚拟内存

Linux 物理内存、虚拟内存_虚拟内存_02

程序是不能直接访问内存条当中的数据的,它通过映射机制,每个程序对应虚拟地址,每个程序通过地址映射这么一个功能映射到内存条对应的物理地址上面去。

虚拟内存的特点如下:

  • 虚拟内存地址和物理内存地址类似,都是为数据提供位置索引
  • 虚拟内存地址和物理内存地址通过映射关系来关联
  • 不同进程都有自己的一套虚拟内存地址,用来给自己的进程空间编号
  • 进程的虚拟内存地址相互独立。因此,两个进程空间可以有相同的虚拟内存地址,如0x10001000。
  • 应用程序的数据读写操作的是虚拟地址,它只能和虚拟内存地址进行交互,对物理内存地址一无所知,也就是对内存条是一无所知的。
  • 程序中表达的内存地址,也都是虚拟内存地址。
  • 进程对虚拟内存地址的操作,会被操作系统翻译成对某个物理内存地址的操作。

借助于虚拟内存地址,操作系统可以保证进程空间的独立性,不同进程就不可能去篡改对方的数据,进程出错的可能性就大大的减少了。

有了虚拟内存,内存共享也变得简单了,操作系统可以将同一个物理内存区域,对应到多个进程空间,这样就不需要任何的数据复制,多个进程就可以看到相同的数据,内核和共享库的映射其实就是通过这种方法实现的。

内存分段:它是根据程序的逻辑角度分成了栈段堆段,数据段,代码段。这样可以分类出不同属性的段,同时是一块连续的空间,但是每个段的大小都是不统一的,这样可能导致内存碎片或者内存交换效率低。

于是就出现了内存的分页,将虚拟空间和物理空间分为固定大小的页,如在linux当中每个页大小为4k,分页之后就不会产生细小的内存碎片,同时在内存交换的时候,写入硬盘也是以页的形式,这样就大大提高了内存交换的效率。

为了解决分页产生的页表过大的问题,那么就有了多级页表,它解决了空间上面的问题,但是这就导致cpu在寻址的过程当中有很多层表层,加大了时间上面的开销,于是在cpu上加入了TLB,负责缓存最经常使用的页表项,大大提高了地址转换的速度。

补充 

Linux 允许进程在申请内存的时候是 overcommit 的,这是什么意思呢?就是说允许进程申请超过实际物理内存上限的内存。 

为了让你更好地理解,我给你举个例子说明。比如说,节点上的空闲物理内存只有 512MB 了,但是如果一个进程调用 malloc() 申请了 600MB,那么 malloc() 的这次申请还是被允许的。

这是因为 malloc() 申请的是内存的虚拟地址,系统只是给了程序一个地址范围,由于没有写入数据,所以程序并没有得到真正的物理内存。物理内存只有程序真的往这个地址写入数据的时候,才会分配给程序。 

可以看得出来,这种 overcommit 的内存申请模式可以带来一个好处,它可以有效提高系统的内存利用率。

举报

相关推荐

0 条评论