Linux内存管理初探

8 篇文章 0 订阅

总结自网络资料,做了部分验证。

——————————————————————————————————————————

Linux为进程提供4GB的虚拟内存(如果不了解虚拟内存,就当成物理内存)。如果把内存想象成从地址低到高的顺序表,竖着放,地址高在上,低在下。(更严谨一点,小端模式下)

则从上到下,从高到低,内存中储存的内容依次为:

内核

栈 ↓

MMAP ↓

堆 ↑

.bss

.data

.rodata

.text

保留区域

1、内核

大小1GB。

用户代码不可访问,内核态可访问。

2、栈

上面是内核,不可访问,正好作为栈底。

大小8MB,储存函数相关内容:函数返回点、函数参数、临时变量。

函数结束时,依次将上述内容出栈,最后返回函数调用点,执行后续代码。

由编译器分配,速度快。

可以通过alloca手动申请。

增加的内容向下扩展。

3、MMAP

此区域用于一一映射文件中的内容,像操作文件一样操作内存,操作系统会在一定延时后将修改写入磁盘,可以通过调用函数设置无延时。 <sys/mman.h> mmap()

增加的内容向下扩展。

4、堆

用于动态申请的内存。

由于申请和释放并不同步,所以堆上通常有大量内存碎片,每个内存碎片起始处储存当前碎片的大小和下一个碎片的起始地址,形成链表一样的结构。

程序员动态申请内存时,程序查找链表上合适的内存段分配,然后将新形成的碎片的信息加入链表,释放时进行类似的操作。

堆的申请由C/C++函数库提供,涉及复杂的算法,申请速度相对较慢。

增加的内容向上扩展。

5、.bss

在程序的物理文件中,未初始化的全局变量和静态变量不需要空间储存,但仍需记录总大小。程序运行时在BSS段内存分配记录大小的全零区域。运行时为它们赋值不会把它们存到其他地方。

6、.data

已初始化的全局变量、静态变量储存在这片区域。

7、.rodata

只读数据区。

常量储存在这片区域

注:部分资料可能将上面的部分区域归到一起

7、.text

可执行文件的代码,包括操作码和操作对象,这片区域一般只读。

8、保留区域

不可访问。

———————————————————————————————————————————

测试代码,依次打印上述各区域中的内容地址。

可以看到从堆到MMAP的区域是最大的。

#include <cstdio>
#include <sys/mman.h>
#include <unistd.h>

int d;

const int e = 0;

void fun()
{
    int f;
    printf("%p\n", &f);
}

int main()
{
    //函数main中的临时变量,在栈中
    int a;
    printf("%p\n", &a);

    // fun中变量后入栈,地址应小于a
    fun();

    // MMAP区
    auto b = mmap(nullptr, getpagesize(), PROT_READ, MAP_SHARED, fileno(fopen("text", "w+")), 0);
    printf("%p\n", b);

    // 由new动态申请的
    auto c = new int;
    printf("%p\n", c);

    // 未初始化全局变量
    printf("%p\n", &d);

    // 已初始化全局变量
    printf("%p\n", &e);
}

输出:
0x7ffc1f35f65c
0x7ffc1f35f63c
0x7fe75f8e9000
0x20d8250
0x601060
0x40088c

上述为运行程序内存结构。

未运行的程序包括:

.bss        未初始化全局变量或静态变量,不占物理空间,但记录总大小

.data        已初始化全局变量或静态变量、常量,占物理空间

.text        代码段

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值