×

Android系统的内存管理探究分析

消耗积分:1 | 格式:rar | 大小:0.4 MB | 2017-10-19

分享资料个

1 Android系统概述
  Android是Google(谷歌)公司开发的一款专门为移动设备打造的操作系统。2005年谷歌公司收购Android Inc公司后,于2007年研发了基于Linux的操作系统Android。2008年,TMobile与HTC公司共同研发了第一款Android手机——HTC G1。Android的发展速度非常惊人,仅仅3年便超过了Symbian系统,并且有强大的OEM支持以及众多的开发者。
  Android基于Linux平台,主要由操作系统、中间件、用户界面和应用软件组成。采用的是软件堆栈的结构,操作系统的底层仅提供最基本的系统功能。在Android系统中,基本上使用的是标准的Linux2.6内核,但是Google为了让Android更适合移动手持设备,对Linux内核进行了各种优化和增强。除了Linux的通用代码外,主要包含体系结构和处理器、Android特定的驱动程序和标准的设备驱动程序3个方面的内容。Android对Linux内核的增强主要包括Alarm(硬件闹钟)、Ashmem(匿名内存共享)、Low Memory Killer(低内存管理)、Logger(日志管理)等。本文将集中分析Android的内存管理,因为Android系统是在Linux系统的基础上发展起来的,所以在介绍Linux基本的内存管理的基础上对Android的内存管理进行研究。
  2 Linux内存管理
  在内存管理方面,Linux系统新旧两个版本(2.6之前和之后)之间有很大的不同。由于Android系统是基于Linux2.6.x内核的,本文主要介绍Linux2.6在内存管理方面的基本内容。
  2.1 反向映射机制
  Linux2.6引入了基于对象的反向映射机制,这种方法为物理页面设置一个用于反向映射的链表,但是链表上的节点并不是引用了该物理页面的所有页表项,而是相应的虚拟内存区域(vm_area_struct结构)。虚拟内存区域通过内存描述符(mm_struct结构)找到页全局目录,从而找到相应的页表项。相对于前一种方法来说,用于表示虚拟内存区域的描述符比用于表示页面的描述符要少得多,所以遍历后边这种反向映射链表所消耗的时间也会少很多。
  page结构中与基于对象的反向映射相关的关键字段有两个:_mapcount和mapping。基于对象的反向映射的实现如下:
  struct page{
  atomic_t_mapcount;
  union{
  ……
  struct{
  ……
  struct address_space*mapping;
  };
  };
  字段_mapcount表明共享该物理页面的页表项的数目,该计数器可用于快速检查该页面除所有者之外有多少使用者在使用,初始值是-1,每增加一个使用者,该计数器加1。
  字段mapping用于区分匿名页面和基于文件映射的页面。如果该字段的最低位置被置位,那么该字段包含的是指向anon_vma结构(用于匿名页面)的指针;否则,该字段包含指向address_space结构的指针(用于基于文件映射的页面)。
  2.2 Linux页面回收
  Linux中页面回收主要通过两种方式触发:一种是由“内存严重不足”事件触发;另一种是由后台进程kswapd触发,该进程周期性地运行,一旦检测到内存不足,就会触发页面回收操作。这里主要介绍shrink_zone()函数,此函数是Linux操作系统实现页面回收的最核心的函数之一,它实现了对一个内存区域的页面进行回收的功能。该函数主要做了两件事:
  ① 将某些页面从active链表移到inactive链表,这是由函数shrink_active_list()实现的;
  ② 从inactive链表中选定一定数目的页面,将其放到一个临时链表中,这由函数shrink_inactive_list()完成。
  该函数最终会调用shrink_page_list()去回收这些页面。
  2.3 OOMKiller机制
  OOM(Out of Memory)是标准Linux内核(kernel)的一种内存管理机制,当系统内存耗尽时,OOM会选择性的杀掉一些进程以求释放一些内存。
  Linux在2.6.36内核中修正了OOMKiller的行为,跟之前的OOMKiller相比,主要体现在3个方面:第一,将物理内存页面的使用作为基准而不是虚拟地址空间的大小;第二,导出用户策略的控制权;第三,内核有了一个简单而合理的默认策略。
  Linux下有3种Overcommit的策略:0,启发式策略;1,永远允许Overcommit,这种策略适合那些不能承受内存分配失败的应用;2,永远禁止Overcommit,这种策略下系统所能分配的内存不会超过swap+RAM*系数。在Linux系统中,只要存在Overcommit,就可能会有OOMKiller跳出来。当OOMKiller跳出来的时候,期望它可以杀掉没用的且耗内存多的程序,这就需要一个选择目标的策略。Linux下这个选择目标的策略也在随着内核的改进不断的演化。在Linux下每个进程都会有个OOM权重,在/proc/《pid》/oom_adj中,取值是-17~+15,取值越高,越容易被杀掉。用户可以通过设置这些值来影响OOMKiller作出决策。这个值是系统综合进程的内存消耗量、CPU时间、存活时间和oom_adj计算出的,消耗内存越多分值就会越高。除此之外,Linux在计算进程的内存消耗的时候,会将子进程所耗内存的一半同时算到父进程中。
  3 Android的低内存管理
  Android是一个多任务系统,当启动一个程序时会消耗一定的时间。为了加快运行速度,当退出一个程序时,Android并不会立即杀掉它,这样当用户重新运行该程序时,可以很快地启动。但随着系统中保留的程序越来越多,内存肯定会出现不足,此时就有了Android的低内存管理(Low Memory Killer)机制。
  3.1 Low Memory Killer机制
  Low Memory Killer是在标准Linux kernel的OOM基础上修改而来的一种内存管理机制,基于oom_adj和占用内存的大小来选择Bad进程。对应于每个oom_adj都有一个空闲内存的阈值,Android kernel每隔一段时间会检查当前空闲内存是否低于某个阈值。如果是,则杀死oom_adj最大的Bad进程。如有两个以上的Bad进程oom_adj相同,则杀死其中占用内存最多的进程。
  3.2 Low Memory Killer的实现
  Low Memory Killer是以内核驱动的形式实现的,该实现位于drivers/misc/lowmemorykiller.c中,通过注册Cache Shrinker实现。Cache Shrinker是标准Linux kernel回收页面的一种机制,它由内核线程kswapd监控,当空闲内存页面不足时,kswapd会调用注册的Shrinker回调函数,来回收内存页面。lowmem_shrink是这个驱动的核心实现,当内存不足时就会调用lowmem_shrink方法来杀掉某些内存。lowmem_shrink用两个数组作为选择Bad进程的依据,定义如下:
  static int lowmem_adj[6]={0,1,6,12};
  static int lowmem_adj_size=4;
  static size_t lowmem_minfree[6]={3*512,2*1024,4*1024,16*1024};
  lowmem_minfree保存空闲内存的阈值,单位是一个页面4 KB,lowmem_adj保存每个阈值对应的优先级。lowmem_shrink首先计算当前空闲内存的大小,如果小于某个阈值,则以该阈值对应的优先级为基准,遍历各个进程,计算每个进程占用内存的大小,找出优先级大于基准优先级的进程,在这些进程中选择优先级最大的杀死。如果优先级相同,则选择占用内存最多的进程。lowmem_shrink杀死进程的方法是向进程发送一个不可以忽略或阻塞的SIGKILL信号:force_sig(SIGKILL,selected)。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"//m.obk20.com/www/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.obk20.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'Android系统的内存管理探究分析',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"https://www.elecfans.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);