谁在消耗电池/span>
人们对手机、笔记本电脑等移动设备的依赖越来越大。一旦电池用尽而又不能立刻充电,便可能把人急得双脚跳。面对类似情况,为了让笔记本电池多支撑一会儿,我会采取两项省电措施:一是把屏幕调暗,二是杀掉特别费电的软件。第一项容易理解,略去不谈。第二项的关键是如何找到高功耗软件。一种简单的方法是调出任务管理器,通过View菜单(Windows 8之前)或者在列表的标题行(Windows 8/8.1)调出图1所示的“选择列”对话框,然后将Page faults(缺页异常总次数)和PF Delta(自上次更新后缺页异常的新增次数,默认为每秒更新一次)两项选中。接下来分别按Page faults、PF Delta和CPU使用率指标对进程排序,找出这几项指标高的进程。
图2 Alipay三个进程的Page faults总数垄断前三名
因为处理每次Page fault时要执行比较复杂的逻辑,所以高Page faults也常意味着较高的CPU使用率。在图2中,AlipaySecSvc进程使用的CPU总时间高达1小时20分32秒。今天的CPU速度惊人,很多“分量”轻的软件运行一天可能也用不上CPU几秒钟(大多被挂起)。尽管AlipaySecSvc的名字中也包含安全字样(Sec),但其CPU总时间如此高也着实离谱。简而言之,这个进程的分量重得惊人。
AlipaySecSvc
那么,如此重的AlipaySecSvc进程是做什么的呢奇心和职业精神都驱使我深入了解这个进程。打开系统服务控制台,找到AlipaySecSvc服务,查看其属性(如图3),可以看到它的全称(Alipay security service)、官方身份和在磁盘上的位置信息。
图4 Alipay软件的磁盘布局
图3中的描述信息声明了AlipaySecSvc服务的重要性,但同时也说明了它的职权范围是“电子支付”。既然如此,当用户未做支付操作时,AlipaySecSvc应该尽可能保持安静。但事实上,它却始终忙碌着,甚至连浏览器进程没有启动时也是如此,这便不正常了。
上调试器
不轻信,不迷信,还是请出WinDBG来看分明。以管理员身份运行WinDBG,赐予其系统级的督察权利,然后将其附加到AlipaySecSvc进程。
接下来的目标是寻找这个进程躁动的原因。如何做呢多种方法,例如以前介绍过的使用~*e .ttime命令观察每个线程的执行时间,再例如使用~* k命令显示每个线程的栈回溯,寻找线索。对于眼下的问题,这两种方法也都有效。但为了避免陈词滥调,这次我打算介绍种新方法。
简单说,就是让被调试对象在调试器里跑一跑,让其“自露马脚”。套用赵本山的话就是“有病没病走两步”。轻扣键盘,发出g命令,恢复AlipaySecSvc运行,端起茶杯,等待WinDBG 告“蛛丝马迹”。
手里的茶杯还没放下,WinDBG便有所发现。屏幕上出现如下信息。
(27bc.1b30): Unknown exception – code 000006ba (first chance)
看来是有真的异常(Windows系统的结构化异常SEH)发生。继续观察,WinDBG连续输出这样的信息,间隔不到一秒。根据经验,这个信息很有价值,可以作为突破口。轻按Ctrl+Break再将AlipaySecSvc断下,然后通过菜单Debug→Event Filters调出图5所示的调试事件过滤器对话框。
图6 过滤器命令
执行如上操作,再恢复AlipaySecSvc运行,让其再走些步。这时我们看到屏幕上持续输出信息,如图7所示(此图为后补,与图1不属同一次调试)。
看来是有人调用了著名的RaiseException API发起软件异常。是发生了什么矛盾,以至于要引爆炸弹呢一下看缘由吧,结果如图8所示。
细看图8,关注本专栏的读者一定可以看出个“破绽”,符 不精确。是的,诚然老雷偷懒了,没有使用PDB ,只用了导出符 。但对于我们的分析,这样的信息足够了。因为其中包含了以下重要内容:
- AlipaySecSvc服务调用了WTSEnumerate-Sessions API。
- WTSEnumerateSessionsW函数(WTS-Enumerate-Sessions API的Unicode版本实现)使用了RPC机制在做远程调用。
- RPC机制的运行时模块(rpcrpt4)检测到不正常情况,“大为关火”,抛出了异常。
有了这些信息,已没必要探究RPC检测到了何种意外,因为我们有了如下结论:AlipaySecSvc服务调用了一个依赖RPC机制的沉重API,而且API执行不顺利,导致了异常。
根据前面的监视结果(见图7),6ba异常是反复发生的,说明这个沉重的过程也是在循环进行。对wtsapi32!WTSEnumerateSessionsW设置断点,果然反复命中,还不止一个线程命中断点,居然有多个线程在调用这个沉重的API和触发异常。从其中的线程ID来看,也有两个(6960和1032)。综合前面的分析,可以对AlipaySecSvc服务进程的躁动原因做出初步诊断:多个线程循环调用沉重的WTSEnumerateSessions API,而且执行时触发异常。
图9 使用WPA分析CPU占用情况
API的分量
使用同样的方法分析缺页异常总数排名第二和第三的Alipaybsm(Browser Safe Monitor)以及TaobaoProtect,结果与此相似,或许它们三兄弟在共享循环调用沉重API的经典代码吧,也可能它们都出自一位同行之手。
普通世界中的商品都明确标识重量。这个基本属性非常重要,尤其在今天的 购时代,买家可能根据重量判断货物的质量,卖家很可能根据重量计算运输(快递)成本。但在软件世界中,标记代码的重量还没有任何规范,甚至尚无测量代码重量的标准方法。更严重的是,很多程序员同行会认为,代码有什么重量呢/p>
如果说为所有普通函数标记重量还为时过早,那么给操作系统的标准API标识重量该排上议事日程了。这不仅必要而且可行。例如用可能引发的系统调用次数、跨进程调用的次数、触发缺页异常的次数等指标来衡量API的重量。标记之后,程序员就有所依据,避免频繁调用太重的API,尤其不要在当前没有明确任务的进程中调用这些沉重的API,以免白白消耗电池,让用户反感。
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!