android -- WatchDog看门狗分析
在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系统的陷入停滞状态,发生不可预料的后果,所以出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测单片机程序运行状态的芯片,俗称"看门狗"。
在Android系统中也需要看好几个重要的Service门,用于发现出了问题的Service杀掉SystemServer进程,所以有必要了解并分析其系统问题。
那么被监控的有哪些Service呢?
ActivityManagerService.java :frameworks\base\services\java\com\android\server\am
PowerManagerService.java :frameworks\base\services\java\com\android\server
WindowManagerService.java :frameworks\base\services\java\com\android\server
下面就依次分析一下其整个处理流程:
1、初始化
run @ SysemServer.java
Slog.i(TAG, "Init Watchdog");
Watchdog.getInstance().init(context, battery, power, alarm,
ActivityManagerService.self());
这里使用单例模式创建:
public static Watchdog getInstance() {
if (sWatchdog == null) {
sWatchdog = new Watchdog();
}
return sWatchdog;
}
public void init(Context context, BatteryService battery,
PowerManagerService power, AlarmManagerService alarm,
ActivityManagerService activity) {
// 上下文环境变量
mResolver = context.getContentResolver();
mBattery = battery;
mPower = power;
mAlarm = alarm;
mActivity = activity;
// 登记 RebootReceiver() 接收,用于reboot广播接收使用
context.registerReceiver(new RebootReceiver(),
new IntentFilter(REBOOT_ACTION));
...
// 系统启动时间
mBootTime = System.currentTimeMillis();
}
ok,调用init函数启动完毕
2、运行中
run @ SysemServer.java
调用 Watchdog.getInstance().start(); 启动看门狗
首先看下 Watchdog 类定义:
/** This class calls its monitor every minute. Killing this process if they don't return **/
public class Watchdog extends Thread {
}
从线程类中继承,即会在一个单独线程中运行,调用thrrad.start()即调用 Watchdog.java 中的 run() 函数
public void run() {
boolean waitedHalf = false;
while (true) {
mCompleted = false;
// 1、给mHandler发送 MONITOR 消息,用于请求检查 Service是否工作正常
mHandler.sendEmptyMessage(MONITOR);
synchronized (this) {
// 2、进行 wait 等待 timeout 时间确认是否退出循环
long timeout = TIME_TO_WAIT;
// NOTE: We use uptimeMillis() here because we do not want to increment the time we
// wait while asleep. If the device is asleep then the thing that we are waiting
// to timeout on is asleep as well and won't have a chance to run, causing a false
// positive on when to kill things.
long start = SystemClock.uptimeMillis();
while (timeout > 0 && !mForceKillSystem) {
try {
wait(timeout); // notifyAll() is called when mForceKillSystem is set
} catch (InterruptedException e) {
Log.wtf(TAG, e);
}
timeout = TIME_TO_WAIT - (SystemClock.uptimeMillis() - start);
}
// 3、如果 mCompleted 为真表示service一切正常,后面会再讲到
if (mCompleted && !mForceKillSystem) {
// The monitors have returned.
waitedHalf = false;
continue;
}
// 4、表明检测到了有 deadlock-detection 条件发生,利用 dumpStackTraces 打印堆栈依信息
if (!waitedHalf) {
// We've waited half the deadlock-detection interval. Pull a stack
// trace and wait another half.
ArrayList<Integer> pids = new ArrayList<Integer>();
pids.add(Process.myPid());
ActivityManagerService.dumpStackTraces(true, pids, null, null);
waitedHalf = true;
continue; // 不过这里会再次检测一次
}
}
SystemClock.sleep(2000);
// 5、打印内核栈调用关系
// Pull our own kernel thread stacks as well if we're configured for that
if (RECORD_KERNEL_THREADS) {
dumpKernelStackTraces();
}
// 6、ok,系统出问题了,检测到某个 Service 出现死锁情况,杀死SystemServer进程
// Only kill the process if the debugger is not attached.
if (!Debug.isDebuggerConnected()) {
Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name);
Process.killProcess(Process.myPid());
System.exit(10);
} else {
Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
}
waitedHalf = false;
}
}
主要工作逻辑:监控线程每隔一段时间发送一条 MONITOR 线另外一个线程,另个一个线程会检查各个 Service 是否正常运行,看门狗就不停的检查并等待结果,失败则杀死SystemServer.
3、Service 检查线程
/**
* Used for scheduling monitor callbacks and checking memory usage.
*/
final class HeartbeatHandler extends Handler {
@Override
public void handleMessage(Message msg) { // Looper 消息处理函数
switch (msg.what) {
case MONITOR: {
// 依次检测各个服务,即调用 monitor() 函数
final int size = mMonitors.size();
for (int i = 0 ; i < size ; i++) {
mCurrentMonitor = mMonitors.get(i);
mCurrentMonitor.monitor();
}
// 检测成功则设置 mCompleted 变量为 true
synchronized (Watchdog.this) {
mCompleted = true;
mCurrentMonitor = null;
}
下面我们来看一下各个Service如何确定自已运行ok呢?以 ActivityManagerService 为例:
首先加入检查队列:
private ActivityManagerService() {
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
}
然后实现 monitor() 函数:
/** In this method we try to acquire our lock to make sure that we have not deadlocked */
public void monitor() {
synchronized (this) { }
}
明白了吧,其实就是检查这个 Service 是否发生了死锁,对于此情况就只能kill SystemServer系统了。对于死锁的产生原因非常多,但有个情况需要注意:java层死锁可能发生在调用native函数,而native函数可能与硬件交互导致时间过长而没有返回,从而导致长时间占用导致问题。
4、内存使用检测
消息发送
final class GlobalPssCollected implements Runnable {
public void run() {
mHandler.sendEmptyMessage(GLOBAL_PSS);
}
}
检测内存处理函数:
final class HeartbeatHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case GLOBAL_PSS: {
if (mHaveGlobalPss) {
// During the last pass we collected pss information, so
// now it is time to report it.
mHaveGlobalPss = false;
if (localLOGV) Slog.v(TAG, "Received global pss, logging.");
logGlobalMemory();
}
} break;
其主要功能如下,统计pSS状况及读取相关linux内核中内存信息:
void logGlobalMemory() {
mActivity.collectPss(stats);
Process.readProcLines("/proc/meminfo",
mMemInfoFields, mMemInfoSizes);
Process.readProcLines("/proc/vmstat",
mVMStatFields, mVMStatSizes);
}
android -- WatchDog看门狗分析的更多相关文章
- 服务器watchdog看门狗的理解
1.什么是watchdog?watchdog,中文名称叫做“看门狗”,全称watchdog timer,从字面上我们可以知道其实它属于一种定时器.然而它与我们平常所接触的定时器在作用上又有所不同.普通 ...
- Resin 的watchdog(看门狗)介绍和resin负载均衡实现
为了稳定和安全,Resin使用一个独立的watchdog进程来启动和监视Resin服务器.watchdog连续你检测Resin服务器的状态,如果其没有反应或者迟钝,将会重启Resin服务器进程.大多数 ...
- 【分享】iTOP-iMX6UL开发板驱动看门狗 watchdog 以及 Linux-c 测试例程
iTOP-iMX6UL开发板看门狗测试例程,iTOP-iMX6UL 开发板的看门狗驱动默认已经配置,可以直接使用测试例程. 版本 V1.1:1.格式修改:2.例程修改完善,其中增加喂狗代码.1 看门狗 ...
- RM-Linux驱动--Watch Dog Timer(看门狗)驱动分析
from:http://blog.csdn.net/geekcome/article/details/6595265 硬件平台:FL2440 内核版本:2.6.28 主机平台:Ubuntu 11,04 ...
- 基于S3C2440的嵌入式Linux驱动——看门狗(watchdog)驱动解读
本文将介绍看门狗驱动的实现. 目标平台:TQ2440 CPU:s3c2440 内核版本:2.6.30 1. 看门狗概述 看门狗其实就是一个定时器,当该定时器溢出前必须对看门狗进行"喂狗“,如 ...
- u-boot分析(五)----I/D cache失效|关闭MMU和cache|关闭看门狗
u-boot分析(五) 上篇博文我们按照210的启动流程,对u-boot启动中的设置异常向量表,设置SVC模式进行了分析,今天我们继续按照u-boot的启动流程对以下内容进行分析. 今天我们会用到的文 ...
- shell 之 用linux定时任务crontab和watchdog.sh脚本做软件看门狗
1.简介 看门狗的作用是定期检测服务正常运行,如果发现服务不在了,会重新拉起服务:linux中可以利用系统的定时任务功能crontab定期的去执行watchdog.sh脚本,而watchdog.sh脚 ...
- Linux 软件看门狗 watchdog 喂狗
Linux 自带了一个 watchdog 的实现,用于监视系统的运行,包括一个内核 watchdog module 和一个用户空间的 watchdog程序.内核 watchdog 模块通过 /dev/ ...
- 用go写一个简单的看门狗程序(WatchDog)
简述 因为公司的一些小程序只是临时使用一下(不再维护更新),有的有一些bug会导致崩溃,但又不是很严重,崩溃了重新启动一下就好. 所以写了一个看门狗程序来监控程序,挂了(因为我这里并不关心程序的其他状 ...
随机推荐
- Oracle数据库编程:使用PL/SQL编写触发器
8.使用PL/SQL编写触发器: 触发器存放在数据缓冲区中. 触发器加序列能够实现自动增长. 在触发器中不能使用connit和rollback. DML触发器 ...
- C#用串口接收事件接不全数据的处理
问题描述:都知道用事件dataReceive来处理串口非常的方便,但当一次的数据过长时,就会出现截断数据的情况.比如说发一个指 令,返回一个30个字节的数据,但上位机则分两次来接收者30个数据. 解决 ...
- EasyUI_tree根据数据库数据生成树形结构JSON格式
@Entitypublic class PubComp { @Id private String aguid; // 菜单ID private String pguid; // 父菜单 private ...
- 1016. 部分A+B (15)
正整数A的“DA(为1位整数)部分”定义为由A中所有DA组成的新整数PA.例如:给定A = 3862767,DA = 6,则A的“6部分”PA是66,因为A中有2个6. 现给定A.DA.B.DB,请编 ...
- HTTP原理
HTTP原理 1 简介 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统. HTTP协议的主要特点可概括如下: 1.支持客户/服务器模式. 2.简单快速:客 ...
- AS:加载新版本的SWF文件。
方案一: 文件名+版本号,区别对待不同的版本控制,有设定值后会加上_v_x的后缀名.如:加载主文件 main.swf, 被命名为:Main_v_60.swf . 方案二: loader.load(ne ...
- Generate the Jobs script from msdb Database
前两周,由于数据库简繁体的转换,大量的数据库需要转到新的服务器. 在转其中的一台的时候,原先导出来的JOBS脚本不翼而飞(原因至今未明),而恰巧这一台服务器有90多个JOB(看下图恢复后的,注意滚动条 ...
- Asp.net使用jQuery实现数据绑定与分页
使用jQuery来实现Gridview, Repeater等服务器端数据展示控件的数据绑定和分页.本文的关注重点是数据如何实现数据绑定. Content jQuery的强大和可用性使得其迅速的流行起来 ...
- asp.net架构基础知识--页面以及全局事件
1.asp.net的请求过程,以及对应的处理请求的dll客户的请求页面由aspnet_isapi.dll这个动态连接库来处理,把请求的aspx文件发送给CLR进行编译执行,然后把Html流返回给浏览器 ...
- 前端优化分析 之 javascript引用位置优化
在很多优化法则中都提到,尽量将javascript放到页面底部,这是为什么呢 我通过firebug进行了下简单的分析 看下图 本页面首尾都存在javascript代码 我们分析得出 1.整个页面文档 ...