• android watchdog 学习


      

    一、代码:frameworksaseservicesjavacomandroidserverWatchdog.java

    二、功能:

    1. 自动定时重启
    2. 定时检查回收系统内存
    3. 监测android服务特别是system server和Phone进程的运行状态,必要时重新启动

    三、类图:

    Android WatchDog分析

    Android WatchDog

    1 Android中的WatchDog

    本文主要介绍android framework层中的watchdog,它属于一种软件Watchdog实现。

    WatchDog主要作用:

    1).接收系统内部reboot请求,重启系统。

    2).监护SystemServer进程,防止系统死锁。

    2 WatchDog启动

    WatchDog是在SystemServer进程中被初始化和启动的。在SystemServer 被Start时,各种Android服务被注册和启动,其中也包括了WatchDog的初始化和启动。代码如下:

    Slog.i(TAG, "Init Watchdog");

    Watchdog.getInstance().init(context, battery, power, alarm,ActivityManagerService.self());

    //Watchdog本身继承Thread,是一个线程类。此为WatchDog初始化。

    .在SystemServer Run函数的后半段,将检查系统是否已经准备好运行第三方代码,并通过SystemReady接口通知系统已经就绪。在ActivityManagerService的SystemReady接口的CallBack函数中实现WatchDog的启动

    Watchdog.getInstance().start();

    //以上代码位于/Frameworks/base/services/java/com/android/server/SystemServer.java中。

    3 WatchDog内部架构及主要接口介绍

    WatchDog内部主要部件和接口函数为:HeartbeatHandler、RebootReceiver、RebootRequestReceiver、checkReboot、rebootSystem、Monitor、addMonitor。

    HeartbeatHandler:此为WatchDog的核心,负责对各个监护对象进行监护。

    RebootReceiver:负责接收由AlarManagerService发出的PendingIntent,并进行系统重启。该PendingIntent为WatchDog内部创建,"com.android.service.Watchdog.REBOOT"。

    RebootRequestReceiver:负责接收系统内部发出的重启Intent消息,并进行系统重启。

    checkReboot:判断是否需要重启系统。

    rebootSystem:调用PowerManager的reboot接口重启系统。

    Monitor:每个被监护对象必须要实现的接口,由WatchDog在运行中调用,以实现监护功能。

    addMonitor:将实现了monitor接口的监护对象注册到WatchDog服务中。

    4 WatchDog工作流程

    4.1WatchDog监护对象

    要实现调用WatchDog对其进行监护,则必须实现

    1)WatchDog.Monitor接口,这个接口中只有一个monitor函数。

    2)将该对象注册到WatchDog服务中,在初始化中作如下处理:Watchdog.getInstance().addMonitor(this); 

    在Android中WatchDog运行在SystemServer进程,对其进行监护,而其中监护的服务为以下三个:

    ActivityManagerService、WindowManagerService、PowerMangerService。

    以ActivityManagerService为例:

    /** In this method we try to acquire our lock to make sure that we have not deadlocked */

        public void monitor() {

            synchronized (this) { }

    }

    该接口函数其实内部并不做任何处理,只是去锁一下对象,然后返回。如果对象没有死锁,则过程会很顺利,若对象死锁,则该函数就会挂在这里。

    其它两个Service对象实现的monitor接口函数与Activity类似,也同样是去获取一下锁而已。

    4.2WatchDog监护流程

    在WatchDog启动之后,开始跑run函数。该函数内部为一个无限循环。

    public void run() {

            boolean waitedHalf = false;

            while (true) {

                mCompleted = false;

                mHandler.sendEmptyMessage(MONITOR);

                ...

                while (timeout > 0 && !mForceKillSystem) {

                        try {

                            wait(timeout); 

                            } catch (InterruptedException e) {

                        }

                        timeout = TIME_TO_WAIT - (SystemClock.uptimeMillis() - start);

                        //TIME_TO_WAIT的默认时间为30s。此为第一次等待时间,WatchDog判断对象是否死锁的最长处理时间为1Min。

                    }

                ...

            }

    }

    一开始就会发送一个MONITOR的Message,由HeartbeatHandler负责接收并处理。同时会等待30秒,等待HeartbeatHandler的处理结果。然后才会进行下一步动作。

    在HeartbeatHandler中将会作如下处理:

    public void handleMessage(Message msg) {

                switch (msg.what) {

                    case MONITOR: {

                    ...

                    final int size = mMonitors.size();

                        for (int i = 0 ; i < size ; i++) {

                            mCurrentMonitor = mMonitors.get(i);

                            mCurrentMonitor.monitor();

                        }//依次去调用监护对象的monitor接口,实现对其的监护。具体操作内容见4.1。

                     synchronized (Watchdog.this) {

                            mCompleted = true;

                            mCurrentMonitor = null;

                        }//如果监护的对象都正常,则会很快运行到这里,并对mCompleted赋值为true,表示对象正常返回。mCompleted值初始为false。

    同时在run函数中:if (mCompleted && !mForceKillSystem) {

                        // The monitors have returned.

                        waitedHalf = false;

                        continue;

                       }//如果所有对象在30s内能够返回,则会得到mCompleted = true;则本次监护就结束,返回继续下一轮监护。

    如果在30s内,monitor对象未能返回,mCompleted 值即为false,则会运行到该语句:

                     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;

                    }//会调用ActivityManagerService.java中的dumpStackTraces接口函数。

    在该接口中,主要会对SystemServer进程的stackTrace的信息dump出来,以及检测目前运行App的CPU使用率。由SystemServer进程发送一个SIGNAL_QUIT的进程信号:

    public static File dumpStackTraces(...,...) {

    ...

    Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);

    ...

    // Next measure CPU usage.

    if (processStats != null) {

       processStats.init();

       System.gc();//运行garbage Collector.

       processStats.update();

       ...

    // We'll take the stack crawls of just the top apps using CPU.

        final int N = processStats.countWorkingStats();

        int numProcs = 0;

        for (int i=0; i<N && numProcs<5; i++) {

        ProcessStats.Stats stats = processStats.getWorkingStats(i);

        if (lastPids.indexOfKey(stats.pid) >= 0) {

            numProcs++;

            try {

    Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);

                }

    ...

    }

    该动作发生在第一次等待的30s时间内,monitor对象未返回,由于在调用完ActivityManagerService.java的dumpStackTraces接口函数后,将waitedHalf赋值为true。并返回继续下一轮监护。若紧接着的下一轮监护,在30s内 monitor对象依旧未及时返回,此时

    if (mCompleted && !mForceKillSystem){

    ...

    }

    if (!waitedHalf){

    ...

    }//此时这两个语句都不会运行,则会直接运行到下面部分。这表示系统的监护对象有死锁现象发生,SystemServer进程需要kill并重启。

          // Pass !waitedHalf so that just in case we somehow wind up here without having

                // dumped the halfway stacks, we properly re-initialize the trace file.

                final File stack = ActivityManagerService.dumpStackTraces(

                        !waitedHalf, pids, null, null);

                // Give some extra time to make sure the stack traces get written.

                // The system's been hanging for a minute, another second or two won't hurt much.

                SystemClock.sleep(2000);

                ...

    // Only kill the process if the debugger is not attached.

          if (!Debug.isDebuggerConnected()) {

                    Process.killProcess(Process.myPid());

                    System.exit(10);//在剩下的30s内,做一些收尾工作,如重新初始化trace file。最后直接将SystemServer进程kill,并且退出系统。Init进程会重新启动SystemServer进程,让其回到可用状态。

  • 相关阅读:
    k8s 基础 pod操作
    python 字典 get 小例子
    linux 日志
    python 基础 文件操作
    k8s 基础 k8s架构和组件
    k8s 基础 核心概念
    HDU1272--小希的迷宫(并查集)
    POJ1182--食物链(经典并查集)并查集看不出来系列2
    HDU 3038 How Many Answers Are Wrong (并查集)---并查集看不出来系列-1
    二分快速幂
  • 原文地址:https://www.cnblogs.com/xu-neal/p/3896897.html
Copyright © 2020-2023  润新知