【Linux系统】内存管理(一)

虚拟地址空间:

每个进程都有自己的虚拟内存地址空间,32位操作系统下是4GB的内存空间,这些虚拟内存通过页表映射到实际的物理内存,它们被操作系统的内核维护并被处理器使用。每个进程都有自己的页表,一旦虚拟地址被使用,它们会被所有运行在机器上的软件所使用,包括内核自身。因此虚拟地址空间必须留一些给内核专用(Linux下3G~4G的空间),这并不意味之内核使用如此多的物理内存,而只是意味着内核使用该段地址来映射它所使用的物理内存,内核空间在页表中会被设定特权级标示,内核的代码和数据总是可以被寻址的,并且始终为处理终端或者系统调用做好准备,相反,用户模式的进程地址空间映射总是随着进程的切换而变化。

下面是标准的linux进程的段空间分布:(注意蓝色区域表示映射到屋里内存的虚拟地址,白色区域表示没有映射的区域,)
这里写图片描述

具体分析:

  1. 栈:进程最上面的段是栈,用来保存局部变量和函数参数,一个经常被使用的栈的区域会被保存在cpu cache中,从而加快访问速度。进程中的每个线程都有各自独立的栈。通过压入足够多的数据可以用完所有stack可以映射的空间,这就会导致页错误,从而被Linux的expand_stack()函数所处理,它又会调用acct_stack_growth()来判断是否可以增加栈的大小,如果栈的大小低于RLIMIT_STACK的限制(通常是8MB),那么栈会增长,从而程序会继续运行而不会知道linux内部所为它做的努力。这就是通常的根据要求调整栈大小的机制。然而,如果达到了最大所允许的栈大小,就会导致栈溢出,从而引发一个程序的segmentation fault。当一个映射的栈区域根据需要而扩大了,它是不会随着栈变小而再缩减回来。动态的栈增长是唯一的一种合法的访问未被映射的内存区域的场景。任何访问一个为被映射的内存的行为都会触发一个页错误,从而导致segmentation fault。有一些映射区域是只读的,因此对它的写访问也会导致相同的segmentation faults。

  2. memory mapping segment:栈的下面就是memory mapping segment。这里被内核用来把文件内容直接映射到内存。所有的应用程序都可以使用linux提供的mmap()系统调用或者在windows中使用CreateFileMapping()/MapViewOfFile来进行这样的映射。memory mapping是进行文件I/O的高效方法,所以动态库的加载使用这个方式来实现。当然,也可以进行一些不关联到文件的程序数据的匿名memory mapping。在linux中,如果你通过malloc()来申请一块大的内存,C库就会在memory mapping segment中创建一个匿名memory mapping而不是使用堆空间。这里的“大”意味着大于MMAP_THRESHOLD字节,默认是128kb,可以通过mallopt()来进行调整。

  3. 堆:堆提供了运行时的内存分配。大多数的语言都提供了对堆进行管理的接口。因此满足内存请求就是一个程序的运行时环境和内核之间的接口的问题。在C语言中,这个接口就是malloc以及它的一些伙伴,而在有垃圾回收机制的语言如C#中的接口就是new关键字。如果有足够的堆空间来满足内存请求,它就可易被该语言的运行时环境所管理而不需要内核的干预。否则,堆通过内核提供的系统调用brk()来满足所请求的空间。堆的管理是复杂的,需要成熟的算法,它必须是满足速度和内存使用效率上的折衷。响应一个对堆内存的请求时间是跟具体的场景相关的。实时系统对于着疑问剃就有特殊的要求,所以产生了特殊的分配器。

  4. BSS段:BSS中存放的是没有初始化的静态变量, 它的值没有被程序在代码中设置。BSS内存区是匿名的,它不会映射到任何文件。

  5. Data段:数据段保存的是在代码中被初始化了的变量。这个内存区不是匿名的。它映射了程序二进制文件中包含的被初始化了的变量。所以,如果你在程序中写了static int cntWorkerBees = 10,那么该变量就会保存在数据段并且值为10。请注意,即使数据段会映射一个文件,它也是私有的内存映射,这意味着你更新了内存中额值也不会反应到它所映射的文件中。这是必须的,因为如果你在运行程序中改变了全局变量的值,却要把这个值写到硬盘上,这是不可取的!

  6. 代码段:代码段是只读的并且你所有的代码都会保存在那里。代码段也会映射到内存当中,但是如果你尝试往那个区域去写就会导致一个Segmentation Fault

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值