Android系统稳定性_第1页
Android系统稳定性_第2页
Android系统稳定性_第3页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Android系统稳定性-ANR1.2如何分析ANR问题引起ANR问题的根本原因,总的来说可以归纳为两类:应用进程自身引起的,例如:主线程阻塞、挂起、死循环应用进程的其他线程的CPU占用率高,使得主线程无法抢占到CPU寸间片其他进程间接引起的,例如:当前应用进程进行进程间通信请求其他进程,其他进程的操作长时间没有反馈其他进程的CPU占用率高,使得当前应用进程无法抢占到CPU寸间片分析ANR问题时,以上述可能的几种原因为线索,通过分析各种日志信息,大多数情况下你就可以很容易找到问题所在了。注意:确实有一些ANR问题很难调查清楚,因为整个系统不稳定的因素很多,例如LinuxKernel本身的bug

2、引起的内存碎片过多、硬件损坏等。这类比较底层的原因引起的ANR、可题往往无从查起,并且这根本不是应用程序的问题,浪费了应用开发人员很多时间,如果你从事过整个系统的开发和维护工作的话会深有体会。所以我不能保证了解了本章的所有内容后能够解决一切ANR、可题,如果出现了很疑难的ANR、可题,我建议最好去和做驱动和内核的朋友聊聊,或者,如果问题只是个十万分之一的偶然现象,不影响程序的正常运行,我倒是建议不去理它。1.2.1分析ANR勺利器Android会在ANR生时输出很多有用的信息帮助分析问题原因,我们先来看一下ANR勺异常信息,使用logcat命令查看会得到类似如下的log:/WindowMana

3、ger所在的进程是system_server,进程号是127I/WindowManager(127):Inputeventdispatchingtimedoutsendingtocom.example.anrdemo/com.example.anrdemo.ANRActivity/system_server进程中的ActivityManagerService请求kernel向5033进程发送SIGNAL_QUIT肯求你可以在shell中使用命令达到相同的目的:adbshellkill-35033/和其他的Java虚拟机一样,SIGNAL_QUI如是Dalvik内部支持的功能之I/Process

4、(127):Sendingsignal.PID:5033SIG:3/5033进程的虚拟机实例接收到SIGNAL_QUIT信号后会将进程中各个线程的函数堆栈信息输出到traces.txt文件中/发生ANR的进程正常情况下会第一个输出I/dalvikvm(5033):threadid=4:reactingtosignal3I/dalvikvm(5033):Wrotestacktracesto'/data/anr/traces.txt'/另外还有其他一些进程/随后会输出CPUS用情况E/ActivityManager(127):ANRincom.example.anrdemo(com

5、.example.anrdemo/.ANRActivity)/Reason表示导致ANR'可题的直接原因E/ActivityManager(127):Reason:keyDispatchingTimedOutE/ActivityManager(127):Load:3.85/3.41/3.16/请注意ago,表示ANR生之前的一段时间内的CPU使用率,并不是某一时刻的值E/ActivityManager(127):CPUusagefrom26835msto3662msagowith99%awake:E/ActivityManager(127):9.4%98/mediaserver:9.4

6、%user+0%kernelE/ActivityManager(127):8.9%127/system_server:6.9%user+2%kernel/faults:1823minor.E/ActivityManager(127):+0%5033/com.example.anrdemo:0%user+0%kernelE/ActivityManager(127):39%TOTAL:32%user+6.1%kernel/这里是later,表示ANR®生之后E/ActivityManager(127):CPUusagefrom601msto1132mslaterwith99%awake:

7、E/ActivityManager(127):10%127/system_server:1.7%user+8.9%kernel/faults:5minorE/ActivityManager(127):10%163/InputDispatcher:1.7%user+8.9%kernelE/ActivityManager(127):1.7%127/system_server:1.7%user+0%kernelE/ActivityManager(127):1.7%135/SurfaceFlinger:0%user+1.7%kernelE/ActivityManager(127):1.7%2814/B

8、inderThread#:1.7%user+0%kernelE/ActivityManager(127):37%TOTAL:27%user+9.2%kernel从log中能够知道,发生ANR寸Android为我们提供了两种“利器”:traces文件和CPU®用率。以上做了简单注释,不过稍后再详细分析它们。1.2.2ANR信息是如何输出的我们再来看看这些log是怎样被输出的,这很重要,知其然,也要知其所以然。代码在ActivityManagerService类中,找到它的appNotResponding函数。finalvoidappNotResponding(ProcessRecord

9、app,ActivityRecordactivity,ActivityRecordparent,finalStringannotation)/firstPids和lastPids两个集合存放那些将会在traces中输出信息的进程的进程号ArrayList<Integer>firstPids=newArrayList<Integer>(5);SparseArray<Boolean>lastPids=newSparseArray<Boolean>(20);/mController是IActivityController接口的实例,是为Monkey测试

10、程序预留的,默认为nullif(mController!=null).longanrTime=SystemClock.uptimeMillis();if(MONITOR_CPU_USAGE)(updateCpuStatsNow();/更新CPUf£用率synchronized(this)(/一些特定条件下会忽略ANRif(mShuttingDown)(Slog.i(TAG,"DuringshutdownskippingANR:"+app+""+annotation);return;elseif(app.notResponding)(Slog.i

11、(TAG,"SkippingduplicateANR:"+app+""+annotation);return;elseif(app.crashing)(Slog.i(TAG,"CrashingappskippingANR:"+app+""+annotation);return;/使用一个标志变量避免同一个应用在没有处理完时重复输出logapp.notResponding=true;./当前发生ANR的应用进程被第一个添加进firstPids集合中firstPids.add(app.pid);/dumpStackTr

12、aces是输出traces文件的函数FiletracesFile=dumpStackTraces(true,firstPids,processStats,lastPids,null);StringcpuInfo=null;if(MONITOR_CPU_USAGE)(/MONITOR_CPU_USAGE认为trueupdateCpuStatsNow();/再次更新CPU言息synchronized(mProcessStatsThread)(输出ANR生前一段时间内的CPUS用率cpuInfo=mProcessStatsprintCurrentState(anrTime);info-appendl

13、processStatsgrintCurrentLoad。);infoappend(cpuInfo);输出ANR生后一段时间内的CPUS用率infoappend(processStatsprintCurrentState(anrTime);/将ANR信息同时输出到DropBox中addErrorToDropBox("anr",app,cessName,activity,parent,annotation,cpuInfo,tracesFile,null);./在Android4.0中可以设置是否不显示AN破示对话框,如果设置的话就不会显示对话框,并且会杀掉ANR

14、®程booleanshowBackground=Settings.Secure.getInt(mContext.getContentResolver(),Settings.Secure.ANR_SHOW_BACKGROUND,0)!=0;synchronized(this)if(!showBackground&&!app.isInterestingToUserLocked()&&app.pid!=MY_PID).Process.killProcessQuiet(app.pid);return;./显示anrH示对话框Messagemsg=Message

15、.obtain();HashMapmap=newHashMap();msg.what=SHOW_NOT_RESPONDING_MSG;msg.obj=map;map.put("app",app);if(activity!=null)(map.put("activity",activity);mHandler.sendMessage(msg);有三个关键点需要注意: 当前发生ANR勺应用进程被第一个添加进firstPids集合中,所以会第一个向traces文件中写入信息。反过来说,traces文件中出现的第一个进程正常情况下就是发生ANR勺那个进程。不过有

16、时候会很不凑巧,发生ANR勺进程还没有来得及输出trace信息,就由于某种原因退出了,所以偶尔会遇到traces文件中找不到发生ANR勺进程信息的情况。 dumpStackTraces是输出traces文件的函数,接下来分析这个函数addErrorToDropBox函数将ANRR言息同时输出到DropBox中,它也是个非常有用的日志存放工具,后面也会分析它的作用。publicstaticFiledumpStackTraces(booleanclearTraces,ArrayList<Integer>firstPids,ProcessStatsprocessStats,SparseA

17、rray<Boolean>lastPids,StringnativeProcs)(/系统届性“dalvik.vm.stack-trace-file”用来配置trace信息输出文件StringtracesPath=SystemProperties.get("dalvik.vm.stack-trace-file",null);if(tracesPath=null|tracesPath.length()=0)(returnnull;FiletracesFile=newFile(tracesPath);try(FiletracesDir=tracesFile.getPa

18、rentFile();if(!tracesDir.exists()tracesFile.mkdirs();/FileUtils.setPermissions是个很有用的函数,设置文件届性时经常会用到FileUtils.setPermissions(tracesDir.getPath(),0775,-1,-1);/drwxrwxr-x/clearTraces为true,会删除旧文件,创建新文件if(clearTraces&&tracesFile.exists()tracesFile.delete();tracesFile.createNewFile();FileUtils.set

19、Permissions(tracesFile.getPath(),0666,-1,-1);/-rw-rw-rw-catch(IOExceptione)(Slog.w(TAG,"UnabletoprepareANRtracesfile:"+tracesPath,e);returnnull;/一个重载函数dumpStackTraces(tracesPath,firstPids,processStats,lastPids,nativeProcs);returntracesFile;有两个关键点需要注意: 聪明的你肯定已经知道,之所以trace信息会输出到“/data/anr/tr

20、aces.txt”文件中,就是系统属性“dalvik.vm.stack-trace-file”设置的。你可以通过在设备的shell中使用setprop和getprop对系统属性进行设置和读取: getpropdalvik.vm.stack-trace-filesetpropdalvik.vm.stack-trace-file/tmp/stack-traces.txt每次发生ANR寸都会删除旧的traces文件,重新创建新文件。也就是说Android只保留最后一次发生ANR寸的traces信息,那么以前的traces信息就丢失了么?稍后回答。接着来看重载的dumpStackTraces函数。pr

21、ivatestaticvoiddumpStackTraces(StringtracesPath,ArrayList<Integer>firstPids,ProcessStatsprocessStats,SparseArray<Boolean>lastPids,StringnativeProcs)/使用FileObserver监听应用进程是否已经完成写入traces文件的操作/Android在判断桌面壁纸文件是否设置完成时也是用的FileObserver,很有用的类FileObserverobserver=newFileObserver(tracesPath,FileOb

22、server.CLOSE_WRITE)publicsynchronizedvoidonEvent(intevent,Stringpath)notify();./首先输出firstPids集合中指定的进程,这些也是对ANR问题来说最重要的进程if(firstPids!=null)tryintnum=firstPids.size();for(inti=0;i<num;i+)synchronized(observer)/前面提到的SIGNAL_QUITProcess.sendSignal(firstPids.get(i),Process.SIGNAL_QUIT);observer.wait(2

23、00);提示:如果你在解决其他问题时也需要查看Java进程中各个线程的函数堆栈信息,就可以使用向目标进程发送SIGNAL_QUIT(3)这个技巧。其实这个名称有点误导,它并不会让进程真正退出。1.2.3DropBox刚才留了一个问题:Android只保留最后一次发生ANF®寸的traces信息,那么以前的traces信息就丢失了么?为了增强Android的异常信息收集管理能力,从2.2开始增加了DropBox功能。DropBox(简称D0是系统进程中的一个服务,在system_server进程启动时创建,并且它没有运行在单独的线程中,而是运行在system_server的Server

24、Thread线程中。我们可以将ServerThread称作system_server的主线程,ServerThread线程除了启动并维护各个服务外,还负责检测一些重要的服务是否死锁,这一点到后面的Watchdog部分再分析<!-Watchdog写完后注意补充章节号->。DB被创建的代码如下。SystemServer.javaServerThread.run()Slog.i(TAG"DropBoxService");ServiceManager.addService(Context.DROPBOX_SERVICE服务名称为“dropbox”newDropBoxMa

25、nagerService(context,newFile("/data/system/dropbox");“/data/system/dropbox”是DB指定的文件存放位置。下面来看一下DB服务的主要功能。1.DropBoxManagerServiceDropBoxManagerService(简称DBMS就是DB服务的本尊,它的主要功能接口包括以下几个函数:publicvoidadd(DropBoxManager.Entryentry)DBM翳所有要添加的日志都用DropBoxManager.Entry类型的对象表示,通过add函数添加,并且直到目前为止一个Entry对

26、象对应着一个日志文件。publicbooleanisTagEnabled(Stringtag)通过给每一个Entry设置一个tag可以标识不同类型的日志,并且可以灵活的启用/禁用某种类型的日志,isTagEnabled用来判断指定类型的日志是否被启用/禁用了,一旦禁用就不会再记录这种类型的日志。默认是不禁用任何类型的日志的。稍后说明如何启用/禁用日志。publicsynchronizedDropBoxManager.EntrygetNextEntry(Stringtag,longmillis)我们可以通过getNextEntry函数获取指定类型和指定时间点之后的第一条日志,要使用这个功能应用程

27、序需要有“android.permission.READ_LOGS”的权限,并且在使用完毕返回的Entry对象后要调用其close函数确保关闭日志文件的文件描述符(如果不关闭的话可能造成进程打开的文件描述符超过1024而崩溃,Android中限制每个进程的文件描述符上限为1024)。DBM洗供了很多的配置项用来限制对磁盘的使用,通过SettingsProvider应用程序维护,数据存放在其settings.db数据库中。这些配置项也都有默认值,罗列如下:Settings.Secure.DROPBOX_AGE_SECONDS="dropbox_age_seconds"日志文件

28、保存的最长时间,默认3天Settings.Secure.DROPBOX_MAX_FILES="dropbox_max_files"日志文件的最大数最,默认值是1000Settings.Secure.DROPBOX_QUOTA_KB="dropbox_quota_kb"磁盘空间最大使用景Settings.Secure.DROPBOX_QUOTA_PERCENT="dropbox_quota_percent"Settings.Secure.DROPBOX_RESERVE_PERCENT="dropbox_reserve_perc

29、ent"Settings.Secure.DROPBOX_TAG_PREFIX="dropbox:"应用程序可以利用DropBox来做事情,收集日志等1.2.4traces.txt终于到大明星出场的时候了,一起来看一下traces.txt的庐山真面目c以下是笔者写的一个演示程序制造出的一次ANR勺trace信息:/文件中输出的第一个进程的trace信息,正是发生ANR勺演示程序/开头显示进程号、ANRt生的时间点和进程名称-pid9183at2012-09-2822:20:42-Cmdline:com.example.anrdemoDALVIKTHREADS:/以下

30、是各个线程的函数堆栈信息/mutexes表示虚拟机实例中各种线程相关对象锁的value值(mutexes:tll=0tsl=0tscl=0ghl=0hwl=0hwll=0)/依次是:线程名、线程优先级、线程创建时的序号、线程当前状态"main"prio=5tid=1TIMED_WAIT/依次是:线程组名称、suspendCount、debugSuspendCount、线程的Java对象地址、线程的Native对象地址|group="main"sCount=1dsCount=0obj=0x4025b1b8self=0xce68/sysTid是线程号,主线程

31、的线程号和进程号相同|sysTid=9183nice=0sched=0/0cgrp=defaulthandle=-1345002368|schedstat=(140838632210998525213)atjava.lang.VMThread.sleep(NativeMethod)atjava.lang.Thread.sleep(Thread.java:1213)atjava.lang.Thread.sleep(Thread.java:1195)atcom.example.anrdemo.ANRActivity.makeANR(ANRActivity.java:44)atcom.example

32、.anrdemo.ANRActivity.onClick(ANRActivity.java:38)atandroid.view.View.performClick(View.java:2486)atandroid.view.View$PerformClick.run(View.java:9130)atandroid.os.Handler.handleCallback(Handler.java:587)atandroid.os.Handler.dispatchMessage(Handler.java:92)atandroid.os.Looper.loop(Looper.java:130)atan

33、droid.app.ActivityThread.main(ActivityThread.java:3703)atjava.lang.reflect.Method.invokeNative(NativeMethod)atjava.lang.reflect.Method.invoke(Method.java:507)ernal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)ernal.os.ZygoteInit.main(ZygoteInit.java:599

34、)atdalvik.system.NativeStart.main(NativeMethod)/Binder线程是进程的线程池中用来处理binder请求的线程"BinderThread#2"prio=5tid=8NATIVE|group="main"sCount=1dsCount=0obj=0x40750b90self=0x1440b8|sysTid=9190nice=0sched=0/0cgrp=defaulthandle=1476256|schedstat=(915528184631354)atdalvik.system.NativeStart.ru

35、n(NativeMethod)"BinderThread#1"prio=5tid=7NATIVE|group="main"sCount=1dsCount=0obj=0x4074f848self=0x78d40|sysTid=9189nice=0sched=0/0cgrp=defaulthandle=1308088|schedstat=(35095232554321210)atdalvik.system.NativeStart.run(NativeMethod)/线程名称后面标识有daemon,说明这是个守护线程"Compiler"da

36、emonprio=5tid=6VMWAIT|group="system"sCount=1dsCount=0obj=0x4074b928self=0x141e78|sysTid=9188nice=0sched=0/0cgrp=defaulthandle=1506000|schedstat=(2160643821636964101)atdalvik.system.NativeStart.run(NativeMethod)/JDWP线程是支持虚拟机调试的线程,不需要关心"JDWP"daemonprio=5tid=5VMWAIT|group="syst

37、em"sCount=1dsCount=0obj=0x4074b878self=0x16c958|sysTid=9187nice=0sched=0/0cgrp=defaulthandle=1510224|schedstat=(36621128076177)atdalvik.system.NativeStart.run(NativeMethod)/"SignalCatcher”负责接收和处理kernel发送的各种信号,例如SIGNAL_QUITSIGNAL_USR1就是被该线程/接收到,这个文件的内容就是由该线程负责输出的,可以看到它的状态是RUNNABLE不过此线程也不需要关

38、心"SignalCatcher"daemonprio=5tid=4RUNNABLE|group="system"sCount=0dsCount=0obj=0x4074b7b8self=0x150008|sysTid=9186nice=0sched=0/0cgrp=defaulthandle=1501664|schedstat=(170898562866219)atdalvik.system.NativeStart.run(NativeMethod)"GC"daemonprio=5tid=3VMWAIT|group="syst

39、em"sCount=1dsCount=0obj=0x4074b710self=0x168010|sysTid=9185nice=0sched=0/0cgrp=defaulthandle=1503184|schedstat=(30517648217782)atdalvik.system.NativeStart.run(NativeMethod)"HeapWorker"daemonprio=5tid=2VMWAIT|group="system"sCount=1dsCount=0obj=0x4074b658self=0x16a080|sysTid=9

40、184nice=0sched=0/0cgrp=defaulthandle=550856|schedstat=(336914072633666915)atdalvik.system.NativeStart.run(NativeMethod)-end9183-pid127at2012-09-2822:20:42-Cmdline:system_server./省略其他进程的信息有一个关键点需要注意:?线程有很多状态,了解这些状态的意义对分析ANR勺原因是有帮助的,总结如下:Thread.java中定义的状态Thread.cpp中定义的状说明态TERMINATEDZOMBIE线程死亡,终止运行RUNN

41、ABLERUNNING/RUNNABLE线程可运行或正在运行执行了帝有超时参数的wait、TIMED_WAITINGTIMED_WAITsleep或join函数BLOCKEDMONITOR线程阻塞,等待获取对象锁执行了洞时参数的wait函WAITINGWAIT数新建,正在初始化,为其分配NEWINITIALIZING资源NEWSTARTING新建,正在启动RUNNABLENATIVE正在执行JNI本地函数WAITINGVMWAIT正在等待VM资源线程暂停,通常是由丁GC或RUNNABLESUSPENDEDdebug被暂停UNKNOWN未知状态Thread.java中的状态和Thread.cpp

42、中的状态是有对应关系的。可以看到前者更加概括,也比较容易理解,面向Java的使用者;而后者更详细,面向虚拟机内部的环境。traces.txt中显示的线程状态都是Thread.cpp中定义的。另外,所有的线程都是遵循POSIX标准的本地线程。关于线程更多的说明可以查阅源码/dalvik/vm/Thread.cpp中的说明。<!-线程的ThreadGroup最好也写进去->traces.txt文件中的这些信息是由每个Dalvik进程的SignalCatcher线程输出的,相关代码可以查看/dalvik/vm/目录下的SignalCatcher.cpp:logThreadStacks函数

43、和Thread.cpp:dvmDumpAllThreadsEx函数。另外请注意,输出堆栈信息时SignalCatcher会暂停所有线程。通过该文件很容易就能知道问题进程的主线程发生ANR寸正在执行怎样的操作。例如上述示例,ANRActivity在makeANI®数中执行线程sleep时发生ANR可以推测sleep时间过长,超过了超时上限导致。这是一种比较简单的情况,实际开发中会遇到很多诡异的、更加复杂的情况,在后面的实例讲解一节会详细说明。1.2.5CPU使用率这部分的内容主要涉及到Linux的相关知识,数据是从“/proc/stat'文件中读取的,Android中仅仅是汇总

44、和记录这些数据而已,熟悉Linux的读者可以跳过本节内容。前面简单说明了CPU®用率信息,我们回顾一下,这次会有更多的知识点要说明。E/ActivityManager(127):ANRincom.example.anrdemo(com.example.anrdemo/.ANRActivity)E/ActivityManager(127):Reason:keyDispatchingTimedOutE/ActivityManager(127):Load:3.85/3.41/3.16/?CPU平均负载/AN收生之前的一段时间内的CPUS用率E/ActivityManager(127):CP

45、Uusagefrom26835msto3662msagowith99%awake:/E/ActivityManager(127):9.4%98/mediaserver:9.4%user+0%kernelE/ActivityManager(127):8.9%127/system_server:6.9%user+2%kernel/faults:1823minor/minor或者major的贞错误次数.E/ActivityManager(127):/+0%5033/com.example.anrdemo:0%user+0%kernelE/ActivityManager(127):39%TOTAL:3

46、2%user+6.1%kernel/AN收生之后的一段时间内的CPUS用率E/ActivityManager(127):CPUusagefrom601msto1132mslaterwith99%awake:E/ActivityManager(127):10%127/system_server:1.7%user+8.9%kernel/faults:5minorE/ActivityManager(127):10%163/InputDispatcher:1.7%user+8.9%kernelE/ActivityManager(127):1.7%127/system_server:1.7%user+0

47、%kernelE/ActivityManager(127):1.7%135/SurfaceFlinger:0%user+1.7%kernelE/ActivityManager(127):1.7%2814/BinderThread#:1.7%user+0%kernel.E/ActivityManager(127):37%TOTAL:27%user+9.2%kernel以上信息其实包含了两个概念:CPU负载和CPU®用率,它们是不同的。不过负载的概念主要是做大型服务器端应用时关注的性能指标,在Android开发中我们更加关注的是使用率。下面详细说明,有八个关键点需要注意:CPU负载/平均

48、负载CPU载是指某一时刻系统中运行队列长度之和加上当前正在CPU上运行的进程数,而CPU¥均负载可以理解为一段时间内正在使用和等待使用CPUW活动进程的平均数景。在Linux中“活动进程”是指当前状态为运行或不可中断阻塞的进程。通常所说的负载其实就是指平均负载。用一个从网上看到的很生动的例子来说明(不考虑CPU寸间片的限制),把设备中的一个单核CPUt匕作一个电话亭,把进程比作正在使用和等待使用电话的人,假如有一个人正在打电话,有三个人在排队等待,此刻电话亭的负载就是4。使用中会不断的有人打完电话离开,也会不断的有其他人排队等待,为了得到一个有参考价值的负载值,可以规定每隔5秒记录一

49、下电话亭的负载,并将某一时刻之前的一分钟、五分钟、十五分钟的的负载情况分别求平均值,最终就得到了三个时段的平均负载。实际上我们通常关心的就是在某一时刻的前一分钟、五分钟、十五分钟的CP坪均负载,例如以上日志中这三个值分别是3.85、3.41、3.16,说明前一分钟内正在使用和等待使用CPU勺活动进程平均有3.85个,依此类推。在大型服务器端应用中主要关注的是第五分钟和第十五分钟的两个值,但是Android主要应用在便携手持设备中,有特殊的软硬件环境和应用场景,短时间内的系统的较高负载就有可能造成ANR所以笔者认为一分钟内的平均负载相对来说更具有参考价值。CPU勺负载和使用率没有必然关系,有可能

50、只有一个进程在使用CPU但执行的是复杂的操作;也有可能等待和正在使用CPU勺进程很多,但每个进程执行的都是简单操作。实际处理问题时偶尔会遇到由于平均负载高引起的ANR典型的特征就是系统中应用进程数最多,CPU总使用率较高,但是每个进程的CPU®用率不高,当前应用进程主线程没有异常阻塞,一分钟内的CPUF均负载较高。提示:Linux内核不断进行着CPU负载的记录,我们可以在任意时刻通过在shell中执行“cat/proc/loadavg”查看。ANR发生之前和之后一段时间的CPU®用率CPU®用率可以理解为一段时间(记作T)内除CPLS闲时间(记作I)之外的时间与这

51、段时间T的比值,用公式表示可以写为:CPU®用率=(T-I)/T而时间段T是两个采样时间点的时间差值。之所以可以这样计算,是因为Linux内核会把从系统启动开始到当前时刻CP姑动的所有时间信息都记录下来,我们可以通过查看“/proc/stat文件获取这些信息。主要包括以下几种时间,这些时间都是从系统启动开始计算的,单位都是0.01秒:user:CPU在用户态的运行时间,不包括nice值为负数的进程运行的时间nice:CPU在用户态并且nice值为负数的进程运行的时间system:CPUB内核态运行的时间idle:CPU空闲时间,不包括iowait时间iowait:CPU等待I/O操作

52、的时间irq:CPU硬中断的时间softirq:CPUC中断的时间注意:随着Linux内核版本的不同,包含的时间类型有可能不同,例如2.6.11中增加的stealstolen等。但根据Android源码,我们只需要关心以上七种类型即可。CPL®用率的计算是在ProcessStats类中实现的。如果在某两个时刻T1和T2(T1<T2)进行采样记录,CPU®用率的整个算法可以归纳为以下几个公式:userTime=(user2+nice2)-(user1+nice1)systemTime=system2-system1idleTime=idle2-idle1iowaitTi

53、me=iowait2-iowait1irqTime=irq2-irqlsoftirqTime=softirq2-softirqlTotalTime=userTime+systemTime+idleTime+iowaitTime+irqTime+softirqTime有了以上数据就可以计算具体的使用率了,例如用户态CPU®用率为:userCpuUsage=userTime/TotalTime依此类推可以计算其他类型的使用率。而整个时间段内CPU®用率为:CpuUsage=(TotalTime-idleTime)/TotalTime以上计算的是整个系统的CPLK用率,对于指定进程的使用率是通过读取该进程的“/proc/进程号/stat”文件计算的,而对于指定进程的指定线程的使用率是通过读取该线程的“/proc/进程号/task/线程号/stat”文件计算的。进程和线程的CPU®用率只包含该进程或线程的总使用率、用户态使用率和内核态使用率。AM睢执行appNotResponding函数过程中,共输出了两个时间段的CPU使用率,通常情

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论