0%

《趣谈linux操作系统》小结(十五) - 内存管理

内存管理

每个进程应该自己的内存空间。内存空间都是独立的、相互隔离的。对于每个进程来讲,看起来应该都是独占的。每个程序对内存的操作都是一致的,内存的管理是进程无关的, 不会因为进程的不同而区别对待,而都是一视同仁的。在最开始的时候,已经了解到程序对内存的操作都是通过虚拟地址实现的,就比如一个大数组,比如超过4kb的大小,已经超过一个页了,但是虚拟地址一定是连续的。只是物理地址就不大可能会是连续的了,通过分段分页的虚拟地址映射实现了物理地址的复用。

独立内存空间

程序的二进制格式都是一致的,仅仅内容、大小不一样而已。进程就是运行的程序,运行过程中还会产生一些数据,运行程序和数据都是放在内存里面的。内存有分页机制,通过虚拟地址和物理的地址的映射可以定位到物理地址。物理地址对进程是不可见的,操作系统的内存管理帮忙作了工作。操作系统会给进程分配一个虚拟地址。所有进程看到的这个地址都是一样的,里面的内存都是从 0 开始编号。在程序里面,指令写入的地址是虚拟地址。当程序要访问虚拟地址的时候,由内核的数据结构进行转换,转换成不同的物理地址,这样不同的进程运行的时候,写入的是不同的物理地址,这样就不会冲突了。

规划虚拟地址空间

操作系统的内存管理,主要分为三个方面。

第一,虚拟内存空间的管理,每个进程看到的是独立的、互不干扰的虚拟地址空间;

第二,物理内存的管理,物理内存地址只有内存管理模块能够使用;

第三,内存映射,需要将虚拟内存和物理内存映射、关联起来。

如果是 32 位,有 2^32 = 4G 的内存空间都是我的,不管内存是不是真的有 4G。如果是 64 位,在 x86_64 下面,其实只使用了 48 位,那也挺恐怖的。48 位地址长度也就是对应了 256TB 的地址空间。至少目前还不需求这么大,过个十几二十年时间没准会突破吧,历史经验。

虚拟空间一切二,一部分用来放内核的东西,称为内核空间,一部分用来放进程的东西,称为用户空间。用户空间在下,在低地址.内核空间在上,在高地址.

用户态空间从最低位开始排起,先是 Text Segment、Data Segment 和 BSS Segment。Text Segment 是存放二进制可执行代码的位置,Data Segment 存放静态常量,BSS Segment 存放未初始化的静态变量。接下来是堆(Heap)段。堆是往高地址增长的,是用来动态分配内存的区域,malloc 就是在这里面分配的。接下来的区域是 Memory Mapping Segment。这块地址可以用来把文件映射进内存用的,如果二进制的执行文件依赖于某个动态链接库,就是在这个区域里面将 so 文件映射到了内存中。再下面就是栈(Stack)地址段。主线程的函数调用的函数栈就是用这里的。

图片替换文本

内核空间和用户空间构造也差不多。一般用不到,暂时不深究了。以后深入研究的时候再抽空了解一下。

cat proc/$PID/maps 可以查看各个地址上是哪些东西。

行动,才不会被动!

欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。