虚拟内存
1.1 虚拟内存
如果在物理内存下,在同一个内存中写入两个程序是不可能的,这会导致程序崩溃,这就需要操作系统为进程分配独立的虚拟地址来进行,各个进程都有自己的地址,互不干扰,这些进程不能访问操作系统的物理内存地址,操作系统会提供一种机制来解决虚拟地址怎么落到物理内存里。
程序中用的地址都是虚拟内存地址,实际上硬件里边的空间是物理内存地址。
虚拟内存地址是由cpu芯片中的MMU进行映射到物理内存地址
1.2 虚拟内存分配方式
1.2.1 内存分段
内存分段分成段选择子和段内偏移量
段选择子中包含段号,段号就是段表的索引,段表中存的是基地址,段的界限,特权等级。
段内偏移量,位于0与段界限之间。
虚拟内存地址是通过段表与物理地址进行映射的
内存分段的缺点:
- 内存碎片,因为当几个进程结束之后,得到的不是连续的内存空间,系统再进行内存分配,导致有外部碎片实现,用内存交换的方式解决
- 内存交换效率低:内部交换,交换的是占很大内存的内部程序,整个机器会显得卡顿。
内存分段的优点
- 产生连续的内存空间
1.2.2 内存分页
分页是将虚拟内存与物理内存空间切割成一段一段固定大小,连续且大小固定的内存空间。
虚拟内存与物理内存通过页表来进行映射。
内存分页的缺点:
- 虚拟内存在页表中查不到的时候会发生缺页异常,进入系统内核空间分配物理内存,更新页表,再返回进程。
- 产生内部碎片
内存分页的步骤
把虚拟内存地址,切分成页号和偏移量
根据页号,从页表里面,查询对应的物理页号
直接拿物理页号,加上前面的偏移量,就得到了物理内存地址。
Linux的内存分配
Linux 系统主要采用了分页管理,但是由于 |ntel 处理器的发展史,Linux 系统无法避免分段管理。于是Linux 就把,所有段的基地址设为0,所有程序的地址空间都是线性地址空间(虚拟地址),相当于屏蔽了 CPU 逻辑地址的概念,所以段只被用于访问控制和内存保护。
Linux 系统中虚拟空间分布可分为用户态和内核态两部分,其中用户态的分布:代码段、全局变量、BSS、函数栈、堆内存、映射区。