Linux中国  设为主页
 收藏本站
 
当前位置: > 首页 ->Linux技术 ->入门与提高 ->Linux操作系统的内存使用方法详细解析
  相关分类: 
入门与提高
系统管理
网络应用
嵌入式系统
内核研究
服务器相关
发行版专区
Linux程序设计
Linux安全
BSD相关
桌面应用
  站内搜索: 
热门文章排行
热门文章排行 新手入门 Linux菜鸟必学的60个命令(04-11)
Linux操作系统下安装QQ最简单的方法(04-11)
即时通讯无界限 LumaQQ的安装和使用(04-11)
Linux 2.6.19.x内核编译配置选项简介(05-09)
Linux版本大全,Linux发行版知多少。(05-06)
精采文章排行
精采文章排行 Ubuntu 7.10扩展Linux系统的多媒体应(01-07)
新手学堂:Samba服务器安装配置过程(01-07)
最简单的Linux系统上的pptpd服务器安(01-07)
新手看招:Linux系统的股票行情分析(01-07)
新手学堂:Linux系统的开机程序执行(01-07)
  ·新手学堂:Samba服务器安装配置过程介绍 ·最简单的Linux系统上的pptpd服务器安装 ·新手看招:Linux系统的股票行情分析软件 ·新手学堂:Linux系统的开机程序执行顺序 ·在Linux操作系统下安装杀毒软件AntiVir ·利用Boot Manager让Vista与Linux双启动 ·如何制作Ubuntu Linux操作系统的本地源 ·2007年度开源10大事件微软起诉Linux居首 ·Ubuntu7.10性能大幅提升要与Vista决高下

Linux操作系统的内存使用方法详细解析

作者:Webmaster   来源:赛迪网技术社区    点击:   日期:2007-05-25 [收藏] [投稿]

  IE是否经常中毒?推荐您

我是一名程序员,那么我在这里以一个程序员的角度来讲解Linux内存的使用。

一提到内存管理,我们头脑中闪出的两个概念,就是虚拟内存,与物理内存。这两个概念主要来自于linux内核的支持。

Linux在内存管理上份为两级,一级是线性区,类似于00c73000-00c88000,对应于虚拟内存,它实际上不占用实际物理内存;一级是具体的物理页面,它对应我们机器上的物理内存。

这里要提到一个很重要的概念,内存的延迟分配。Linux内核在用户申请内存的时候,只是给它分配了一个线性区(也就是虚存),并没有分配实际物理内存;只有当用户使用这块内存的时候,内核才会分配具体的物理页面给用户,这时候才占用宝贵的物理内存。内核释放物理页面是通过释放线性区,找到其所对应的物理页面,将其全部释放的过程。

char *p=malloc(2048) //这里只是分配了虚拟内存2048,并不占用实际内存。

strcpy(p,”123”) //分配了物理页面,虽然只是使用了3个字节,但内存还是为它分配了2048字节的物理内存。

free(p) //通过虚拟地址,找到其所对应的物理页面,释放物理页面,释放线性区。

我们知道用户的进程和内核是运行在不同的级别,进程与内核之间的通讯是通过系统调用来完成的。进程在申请和释放内存,主要通过brk,sbrk,mmap,unmmap这几个系统调用,传递的参数主要是对应的虚拟内存。

注意一点,在进程只能访问虚拟内存,它实际上是看不到内核物理内存的使用,这对于进程是完全透明的。

glibc内存管理器

那么我们每次调用malloc来分配一块内存,都进行相应的系统调用呢?

答案是否定的,这里我要引入一个新的概念,glibc的内存管理器。

我们知道malloc和free等函数都是包含在glibc库里面的库函数,我们试想一下,每做一次内存操作,都要调用系统调用的话,那么程序将多么的低效。

实际上glibc采用了一种批发和零售的方式来管理内存。glibc每次通过系统调用的方式申请一大块内存(虚拟内存),当进程申请内存时,glibc就从自己获得的内存中取出一块给进程。

内存管理器面临的困难

我们在写程序的时候,每次申请的内存块大小不规律,而且存在频繁的申请和释放,这样不可避免的就会产生内存碎块。而内存碎块,直接会导致大块内存申请无法满足,从而更多的占用系统资源;如果进行碎块整理的话,又会增加cpu的负荷,很多都是互相矛盾的指标,这里我就不细说了。

我们在写程序时,涉及内存时,有两个概念heap和stack。传统的说法stack的内存地址是向下增长的,heap的内存地址是向上增长的。

函数malloc和free,主要是针对heap进行操作,由程序员自主控制内存的访问。

在这里heap的内存地址向上增长,这句话不完全正确。

glibc对于heap内存申请大于128k的内存申请,glibc采用mmap的方式向内核申请内存,这不能保证内存地址向上增长;小于128k的则采用brk,对于它来讲是正确的。128k的阀值,可以通过glibc的库函数进行设置。

这里我先讲大块内存的申请,也即对应于mmap系统调用。

对于大块内存申请,glibc直接使用mmap系统调用为其划分出另一块虚拟地址,供进程单独使用;在该块内存释放时,使用unmmap系统调用将这块内存释放,这个过程中间不会产生内存碎块等问题。

针对小块内存的申请,在程序启动之后,进程会获得一个heap底端的地址,进程每次进行内存申请时,glibc会将堆顶向上增长来扩展内存空间,也就是我们所说的堆地址向上增长。在对这些小块内存进行操作时,便会产生内存碎块的问题。实际上brk和sbrk系统调用,就是调整heap顶地址指针。

那么heap堆的内存是什么时候释放呢?

当glibc发现堆顶有连续的128k的空间是空闲的时候,它就会通过brk或sbrk系统调用,来调整heap顶的位置,将占用的内存返回给系统。这时,内核会通过删除相应的线性区,来释放占用的物理内存。

下面我要讲一个内存空洞的问题:

一个场景,堆顶有一块正在使用的内存,而下面有很大的连续内存已经被释放掉了,那么这块内存是否能够被释放?其对应的物理内存是否能够被释放?

很遗憾,不能。

这也就是说,只要堆顶的部分申请内存还在占用,我在下面释放的内存再多,都不会被返回到系统中,仍然占用着物理内存。为什么会这样呢?

这主要是与内核在处理堆的时候,过于简单,它只能通过调整堆顶指针的方式来调整调整程序占用的线性区;而又只能通过调整线性区的方式,来释放内存。所以只要堆顶不减小,占用的内存就不会释放。

 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<

上一页12 3 4 下一页

上一篇:SUSE Linux中Ftp/xinetd服务的开启方法   下一篇:VMware虚拟机 软件安装及使用方法说明
文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论

   相关文章:
·Ubuntu 7.10扩展Linux系统的多媒体应用

   文章评论:(1条)
  
 请留名: 匿名评论   点击查看所有评论 论坛讨论
 

 声明:刊登此文章是为了传递更多信息,文章内容仅供参考,转载请注明出处。