AndroidQ的详细关机流程

一,先直接上流程图

二,代码详细分析

 

1. @frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
            wm = WindowManagerService.main(context, inputManager,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                    !mFirstBoot, mOnlyCore, new PhoneWindowManager());
            ServiceManager.addService(Context.WINDOW_SERVICE, wm);
}

2. @WindowManagerService.java (frameworks\base\services\core\java\com\android\server\wm)
    public static WindowManagerService main(final Context context, final InputManagerService im,
            final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
            WindowManagerPolicy policy) {
        DisplayThread.getHandler().runWithScissors(() ->
                sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
                        onlyCore, policy), 0);
        return sInstance;
    }
    // Called by window manager policy.  Not exposed externally.
    @Override
    public void shutdown(boolean confirm) {
        // Pass in the UI context, since ShutdownThread requires it (to show UI).
        ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(),
                PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
    }

3. @PhoneWindowManager.java (frameworks\base\services\core\java\com\android\server\policy)
没有构造函数?用默认的?
public class PhoneWindowManager implements WindowManagerPolicy {

     mWindowManagerFuncs = windowManagerFuncs;
    @Override 在哪调用?
    public void init(Context context, IWindowManager windowManager,
            WindowManagerFuncs windowManagerFuncs) {
        mContext = context;
        mWindowManager = windowManager;
mWindowManagerFuncs = windowManagerFuncs; //指向 WindowManagerService 
}
    private class PolicyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
                case MSG_POWER_LONG_PRESS:
                    powerLongPress();
                    break;
}
    private void powerLongPress() {
        final int behavior = getResolvedLongPressOnPowerBehavior();  永远是1   !!!!!
        switch (behavior) {
case LONG_PRESS_POWER_GLOBAL_ACTIONS:
showGlobalActionsInternal();
break
        case LONG_PRESS_POWER_SHUT_OFF:
        case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
            mPowerKeyHandled = true;
            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
            mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF); //实际调用WindowManagerService.shutdown
            break;
        }
    }

   void showGlobalActionsInternal() {
        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
        if (mGlobalActions == null) {
            mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
        }
        final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
        mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());显示关机对话框
        if (keyguardShowing) {
            // since it took two seconds of long press to bring this up,
            // poke the wake lock so they have some time to see the dialog.
            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
        }
    }

@GlobalActions.java (frameworks\base\services\core\java\com\android\server\policy)
    public void showDialog(boolean keyguardShowing, boolean deviceProvisioned) {
        mKeyguardShowing = keyguardShowing;
        mDeviceProvisioned = deviceProvisioned;
        mShowing = true;
        if (mStatusBarConnected) {
            mStatusBarInternal.showGlobalActions();   //StatusBarManagerInternal mStatusBarInternal;
            mHandler.postDelayed(mShowTimeout, 5000);
        } else {
            // SysUI isn't alive, show legacy menu.
            ensureLegacyCreated();
            mLegacyGlobalActions.showDialog(mKeyguardShowing, mDeviceProvisioned);
        }
    }

    @StatusBarManagerService.java (frameworks\base\services\core\java\com\android\server\statusbar)
        public void showGlobalActions() {
            if (mBar != null) {
                try {
                    mBar.showGlobalActionsMenu(); //mBar 是CommandQueue
                } catch (RemoteException ex) {}
            }
        }

@StatusBar.java (frameworks\base\packages\systemui\src\com\android\systemui\statusbar\phone)	323521	10/25/2017
        mBarService = IStatusBarService.Stub.asInterface(ServiceManager.getService(Context.STATUS_BAR_SERVICE));
        // Connect in to the status bar manager service
        mCommandQueue = getComponent(CommandQueue.class);
        mCommandQueue.addCallbacks(this);

        try {
            mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders,
                    fullscreenStackBounds, dockedStackBounds);
        } catch (RemoteException ex) {
            // If the system process isn't there we're doomed anyway.
        }

@CommandQueue.java (frameworks\base\packages\systemui\src\com\android\systemui\statusbar)
    public void showGlobalActionsMenu() {
        synchronized (mLock) {
            mHandler.removeMessages(MSG_SHOW_GLOBAL_ACTIONS);
            mHandler.obtainMessage(MSG_SHOW_GLOBAL_ACTIONS).sendToTarget();  //mCallbacks.get(i).handleShowGlobalActionsMenu();
        }
    }
@GlobalActionsComponent.java (frameworks\base\packages\systemui\src\com\android\systemui\globalactions)
    public void handleShowGlobalActionsMenu() {
        mExtension.get().showGlobalActions(this); //mExtension.get() = GlobalActionsImpl
    }

@GlobalActionsImpl.java (frameworks\base\packages\systemui\src\com\android\systemui\globalactions)
    public void showGlobalActions(GlobalActionsManager manager) {
        if (mGlobalActions == null) {
            mGlobalActions = new GlobalActionsDialog(mContext, manager);
        }
        mGlobalActions.showDialog(mKeyguardMonitor.isShowing(),  mDeviceProvisionedController.isDeviceProvisioned());
    }

@GlobalActionsDialog.java (frameworks\base\packages\systemui\src\com\android\systemui\globalactions)
    public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) {
        mKeyguardShowing = keyguardShowing;
        mDeviceProvisioned = isDeviceProvisioned;
        if (mDialog != null) {
            mDialog.dismiss();
            mDialog = null;
            // Show delayed, so that the dismiss of the previous dialog completes
            mHandler.sendEmptyMessage(MESSAGE_SHOW);
        } else {
            handleShow();
        }
    }

    private void handleShow() {
        awakenIfNecessary();
        mDialog = createDialog();  //创建ActionsDialog
        prepareDialog();

        // If we only have 1 item and it's a simple press action, just do this action.
        if (mAdapter.getCount() == 1
                && mAdapter.getItem(0) instanceof SinglePressAction
                && !(mAdapter.getItem(0) instanceof LongPressAction)) {
            ((SinglePressAction) mAdapter.getItem(0)).onPress();
        } else {
            WindowManager.LayoutParams attrs = mDialog.getWindow().getAttributes();
            attrs.setTitle("ActionsDialog");
            mDialog.getWindow().setAttributes(attrs);
            mDialog.show(); //此处显示关机对话框!!!!
            mWindowManagerFuncs.onGlobalActionsShown();
        }
    }

    public void onClick(DialogInterface dialog, int which) {
        Action item = mAdapter.getItem(which);
        if (!(item instanceof SilentModeTriStateAction)) {
            dialog.dismiss();
        }
        item.onPress(); //item = PowerAction 此处处理关机的选项
    }

private final class PowerAction extends SinglePressAction implements LongPressAction {
        @Override
        public void onPress() {
            // shutdown by making sure radio and power are handled accordingly.
            mWindowManagerFuncs.shutdown();  指向 WindowManagerService 
        }
}

4. @WindowManagerService.java (frameworks\base\services\core\java\com\android\server\wm)
public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs 

    // Called by window manager policy.  Not exposed externally.
    @Override
    public void shutdown(boolean confirm) {
        // Pass in the UI context, since ShutdownThread requires it (to show UI).
        ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(),
                PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
    }

5. @ShutdownThread.java (frameworks\base\services\core\java\com\android\server\power)
    // static instance of this thread
    private static final ShutdownThread sInstance = new ShutdownThread();
    public static void shutdown(final Context context, String reason, boolean confirm) {
        mReboot = false;
        mRebootSafeMode = false;
        mReason = reason;
        shutdownInner(context, confirm); -> beginShutdownSequence
    }
    private static void beginShutdownSequence(Context context) {
        sInstance.mProgressDialog = showShutdownDialog(context);
        sInstance.mContext = context;
        sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
        // make sure we never fall asleep again
        sInstance.mCpuWakeLock = null;
        try {
            sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock( 申请一把锁,防止系统休眠
                    PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu");
            sInstance.mCpuWakeLock.setReferenceCounted(false);
            sInstance.mCpuWakeLock.acquire();
        } catch (SecurityException e) {
            Log.w(TAG, "No permission to acquire wake lock", e);
            sInstance.mCpuWakeLock = null;
        }

        // also make sure the screen stays on for better user experience, 此处可以直接黑屏
//添加sInstance.mPowerManager.setBacklightBrightnessOff(true);
        sInstance.mScreenWakeLock = null;
        if (sInstance.mPowerManager.isScreenOn()) {
            try {
                sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock(
                        PowerManager.FULL_WAKE_LOCK, TAG + "-screen");
                sInstance.mScreenWakeLock.setReferenceCounted(false);
                sInstance.mScreenWakeLock.acquire();
            } catch (SecurityException e) {
                Log.w(TAG, "No permission to acquire wake lock", e);
                sInstance.mScreenWakeLock = null;
            }
        }

        // start the thread that initiates shutdown
        sInstance.mHandler = new Handler() {
        };
        sInstance.start(); //开始ShutdownThread.run
    }

    public void run() {
        TimingsTraceLog shutdownTimingLog = newTimingsLog();   耗费时间的输出
        shutdownTimingLog.traceBegin("SystemServerShutdown");
 
BroadcastReceiver br = new BroadcastReceiver() {
            @Override public void onReceive(Context context, Intent intent) {
                // We don't allow apps to cancel this, so ignore the result.
                actionDone();
            }
        };
        /*
         * Write a system property in case the system_server reboots before we
         * get to the actual hardware restart. If that happens, we'll retry at
         * the beginning of the SystemServer startup.
         */
        {
            String reason = (mReboot ? "1" : "0") + (mReason != null ? mReason : "");
            SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);  //SHUTDOWN_ACTION_PROPERTY = sys.shutdown.requested
        }

//1. First send the high-level shut down broadcast. 发送关机广播,最大超时MAX_BROADCAST_TIME=10*1000;
shutdownTimingLog.traceBegin("SendShutdownBroadcast");
        mActionDone = false;
        Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        mContext.sendOrderedBroadcastAsUser(intent,
                UserHandle.ALL, null, br, mHandler, 0, null, null);
shutdownTimingLog.traceEnd(); // 输出 log: SendShutdownBroadcast took to complete: 836ms
2.
        final IActivityManager am =
                IActivityManager.Stub.asInterface(ServiceManager.checkService("activity"));
        if (am != null) {
            try {
                am.shutdown(MAX_BROADCAST_TIME); 关闭activitymanager
            } catch (RemoteException e) {
            }
        }
3.
        final PackageManagerService pm = (PackageManagerService)
            ServiceManager.getService("package");
        if (pm != null) {
            pm.shutdown(); 关闭Packagemanager
        }
4.
shutdownRadios(MAX_RADIO_WAIT_TIME); 关闭无线, 最大超时MAX_RADIO_WAIT_TIME=12*1000;
5. 
       final IStorageManager storageManager = IStorageManager.Stub.asInterface(
                        ServiceManager.checkService("mount"));
      if (storageManager != null) {
                    storageManager.shutdown(observer); 关闭storageManager, 最大超时MAX_SHUTDOWN_WAIT_TIME=20*1000
      } else {
                    Log.w(TAG, "StorageManagerService unavailable for shutdown");
      }

rebootOrShutdown(mContext, mReboot, mReason);
 }

    public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
        if (reboot) {
            Log.i(TAG, "Rebooting, reason: " + reason);
            PowerManagerService.lowLevelReboot(reason);
            Log.e(TAG, "Reboot failed, will attempt shutdown instead");
            reason = null;
        } else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {
            // vibrate before shutting down
            Vibrator vibrator = new SystemVibrator(context);
            try {
                vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES);
            } catch (Exception e) {
                // Failure to vibrate shouldn't interrupt shutdown.  Just log it.
                Log.w(TAG, "Failed to vibrate during shutdown.", e);
            }

            // vibrator is asynchronous so we need to wait to avoid shutting down too soon.
            try {
                Thread.sleep(SHUTDOWN_VIBRATE_MS);持续500ms的震动
            } catch (InterruptedException unused) {
            }
        }
        // Shutdown power
        Log.i(TAG, "Performing low-level shutdown...");
        PowerManagerService.lowLevelShutdown(reason);
    }
6. @PowerManagerService.java (frameworks\base\services\core\java\com\android\server\power)
    public static void lowLevelShutdown(String reason) {
        if (reason == null) {
            reason = "";
        }
        SystemProperties.set("sys.powerctl", "shutdown," + reason);
    }

6.1. @Property_service.cpp (system\core\init) 如何知道和处理system prop的改变
void start_property_service() {
    property_set("ro.property_service.version", "2");

    property_set_fd = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
                                   false, 0666, 0, 0, nullptr, sehandle); 创建socket: dev/socket/property_service,  用于监听
    if (property_set_fd == -1) {
        PLOG(ERROR) << "start_property_service socket creation failed";
        exit(1);
    }
    listen(property_set_fd, 8);
    register_epoll_handler(property_set_fd, handle_property_set_fd);
}

 handle_property_set_fd() 
->handle_property_set(socket, prop_value, prop_value, true);
->property_set(name, value);
->PropertySetImpl(name, value)
->property_changed(name, value);

6.2. @Init.cpp (system\core\init)	
void property_changed(const std::string& name, const std::string& value) {
    // If the property is sys.powerctl, we bypass the event queue and immediately handle it.
    // This is to ensure that init will always and immediately shutdown/reboot, regardless of
    // if there are other pending events to process or if init is waiting on an exec service or
    // waiting on a property.
    // In non-thermal-shutdown case, 'shutdown' trigger will be fired to let device specific
    // commands to be executed.
    if (name == "sys.powerctl") {
        // Despite the above comment, we can't call HandlePowerctlMessage() in this function,
        // because it modifies the contents of the action queue, which can cause the action queue
        // to get into a bad state if this function is called from a command being executed by the
        // action queue.  Instead we set this flag and ensure that shutdown happens before the next
        // command is run in the main init loop.
        // TODO: once property service is removed from init, this will never happen from a builtin,
        // but rather from a callback from the property service socket, in which case this hack can
        // go away.
        shutdown_command = value;
        do_shutdown = true;
    }

    if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyChange(name, value);

    if (waiting_for_prop) {
        if (wait_prop_name == name && wait_prop_value == value) {
            LOG(INFO) << "Wait for property took " << *waiting_for_prop;
            ResetWaitForProp();
        }
    }
}


7. @Init.cpp (system\core\init)	
int main(int argc, char** argv) {
init进程启动*.rc中的进程后,开始处理下列事件等
    while (true) {
        // By default, sleep until something happens.  使用的是epoll机制
        int epoll_timeout_ms = -1;

        if (do_shutdown && !shutting_down) { 等待property_changed中收到sys.powerctl属性的改变,do_shutdown会变为true
            do_shutdown = false;
            if (HandlePowerctlMessage(shutdown_command)) {
                shutting_down = true;
            }
        }

        if (!(waiting_for_prop || sm.IsWaitingForExec())) {
            am.ExecuteOneCommand(); 从ActionManager的执行队列中,取出命令逐个执行
        }
        if (!(waiting_for_prop || sm.IsWaitingForExec())) {
            if (!shutting_down) restart_processes();

            // If there's a process that needs restarting, wake up in time for that.
            if (process_needs_restart_at != 0) {
                epoll_timeout_ms = (process_needs_restart_at - time(nullptr)) * 1000;
                if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
            }

            // If there's more work to do, wake up again immediately.
            if (am.HasMoreCommands()) epoll_timeout_ms = 0;
        }

        epoll_event ev;
        int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));  如何等待的?
        if (nr == -1) {
            PLOG(ERROR) << "epoll_wait failed";
        } else if (nr == 1) {
            ((void (*)()) ev.data.ptr)();
        }
    }
}

8. @Reboot.cpp (system\core\init)
bool HandlePowerctlMessage(const std::string& command) {
    if (cmd_params.size() > 3) {
        command_invalid = true;
    } else if (cmd_params[0] == "shutdown") {
        cmd = ANDROID_RB_POWEROFF;
        if (cmd_params.size() == 2 && cmd_params[1] == "userrequested") {
            // The shutdown reason is PowerManager.SHUTDOWN_USER_REQUESTED.
            // Run fsck once the file system is remounted in read-only mode.
            run_fsck = true;
        }
    } 
    // Queue shutdown trigger first
    ActionManager::GetInstance().ClearQueue(); 清除队列中所有action, 然后再添加shutdown action到ActionManager的执行队列中,main@init.cpp会从该队列中取出命令逐个执行
    ActionManager::GetInstance().QueueEventTrigger("shutdown"); 在哪解析的这个shutdown命令呢?这个直接忽略!!!
    // Queue built-in shutdown_done
    auto shutdown_handler = [cmd, command, reboot_target,
                             run_fsck](const std::vector<std::string>&) {
        DoReboot(cmd, command, reboot_target, run_fsck);
        return 0;
    };
    ActionManager::GetInstance().QueueBuiltinAction(shutdown_handler, "shutdown_done");  关机执行的后期关键函数是shutdown_handler->DoReboot

    // Skip wait for prop if it is in progress
    ResetWaitForProp();

    // Skip wait for exec if it is in progress
    if (ServiceManager::GetInstance().IsWaitingForExec()) {
        ServiceManager::GetInstance().ClearExecWait();
    }

    return true;
}

void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget, bool runFsck) {
{
// optional shutdown step
// 1. terminate all services except shutdown critical ones. wait for delay to finish, "ro.build.shutdown_timeout"
            service_count = 0;
            ServiceManager::GetInstance().ForEachService([&service_count](Service* s) {
                // Count the number of services running except shutdown critical.
                // Exclude the console as it will ignore the SIGTERM signal
                // and not exit.
                // Note: SVC_CONSOLE actually means "requires console" but
                // it is only used by the shell.
                if (!s->IsShutdownCritical() && s->pid() != 0 && (s->flags() & SVC_CONSOLE) == 0) {
                    service_count++;
                }
            });
    // minimum safety steps before restarting
    // 2. kill all services except ones that are necessary for the shutdown sequence.
    ServiceManager::GetInstance().ForEachService([](Service* s) {
        if (!s->IsShutdownCritical()) s->Stop();
    });
    ServiceManager::GetInstance().ReapAnyOutstandingChildren();

    // 3. send volume shutdown to vold
    Service* voldService = ServiceManager::GetInstance().FindServiceByName("vold");
    if (voldService != nullptr && voldService->IsRunning()) {
        ShutdownVold();
        voldService->Stop();
    } else {
        LOG(INFO) << "vold not running, skipping vold shutdown";
    }
    // logcat stopped here
    ServiceManager::GetInstance().ForEachService([&kill_after_apps](Service* s) {
        if (kill_after_apps.count(s->name())) s->Stop();
    });
    // 4. sync, try umount, and optionally run fsck for user shutdown
    sync(); //数据回写到EMMC
    UmountStat stat = TryUmountAndFsck(runFsck, shutdown_timeout - t.duration());
    // Follow what linux shutdown is doing: one more sync with little bit delay
    sync();
    if (!is_thermal_shutdown) std::this_thread::sleep_for(100ms);
    LogShutdownTime(stat, &t);
    // Reboot regardless of umount status. If umount fails, fsck after reboot will fix it.
    RebootSystem(cmd, rebootTarget);
    abort();
}

tatic void __attribute__((noreturn))
RebootSystem(unsigned int cmd, const std::string& rebootTarget) {
    LOG(INFO) << "Reboot ending, jumping to kernel";
    if (!IsRebootCapable()) {
        // On systems where init does not have the capability of rebooting the
        // device, just exit cleanly.
        exit(0);
    }
    switch (cmd) {
        case ANDROID_RB_POWEROFF:
            reboot(RB_POWER_OFF);
            break;
        case ANDROID_RB_RESTART2:
            syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
                    LINUX_REBOOT_CMD_RESTART2, rebootTarget.c_str());
            break;
        case ANDROID_RB_THERMOFF:
            reboot(RB_POWER_OFF);
            break;
    }
    // In normal case, reboot should not return.
    PLOG(FATAL) << "reboot call returned";
    abort();
}

9. @Reboot.cpp (bionic\libc\bionic)
extern "C" int __reboot(int, int, int, void*);
int reboot(int mode) {
  return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL); _reboot通过syscall来到内核
}

10. @bionic/libc/arch-arm/syscalls/__reboot.S
ENTRY(__reboot)
    mov     ip, r7
    .cfi_register r7, ip
    ldr     r7, =__NR_reboot
    swi     #0
    mov     r7, ip
    .cfi_restore r7
    cmn     r0, #(MAX_ERRNO + 1)
    bxls    lr
    neg     r0, r0
    b       __set_errno_internal
END(__reboot)
11. @Linux-syscalls.h (bionic\tools\versioner\platforms\android-9\include\sys)
#define __NR_reboot                       (__NR_SYSCALL_BASE + 88)
其被指定了一个固定的偏移量,在被调用的时候就是通过这个偏移量去内核中寻找对应的入口的,由此可见,内核中一定有着相同的定义,否则将不能成功调用。
内核中对syscall偏移量的定义	在内核源码中的arch/arm/include/asm/unistd.h,相关信息完全一致。

12. @kernel-3.18/arch/arm64/include/asm/unistd32.h
#define __NR_reboot 88
__SYSCALL(__NR_reboot, sys_reboot)

13. @Syscalls.h (kernel-3.18/include\linux)
asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user *arg);
#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)

14. @Reboot.c (kernel-3.18/kernel)
/*
 * Reboot system call: for obvious reasons only root may call it,
 * and even root needs to set up some magic numbers in the registers
 * so that some mistake won't make this reboot the whole machine.
 * You can also set the meaning of the ctrl-alt-del-key here.
 *
 * reboot doesn't sync: do that yourself before calling this.
 */
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
		void __user *, arg)
{
switch (cmd) {
	case LINUX_REBOOT_CMD_POWER_OFF:
		kernel_power_off();
		do_exit(0);
		break;
}

}

/**
 *	kernel_power_off - power_off the system
 *
 *	Shutdown everything and perform a clean system power_off.
 */
void kernel_power_off(void)
{
	kernel_shutdown_prepare(SYSTEM_POWER_OFF);
	if (pm_power_off_prepare)
		pm_power_off_prepare();
	migrate_to_reboot_cpu();
	syscore_shutdown();
	pr_emerg("Power down\n");
	kmsg_dump(KMSG_DUMP_POWEROFF);
	machine_power_off();
}
由此进入kernel的关机流程了,以后再继续分析!!!

static void kernel_shutdown_prepare(enum system_states state)
{
	blocking_notifier_call_chain(&reboot_notifier_list,  通知注册过监听关机或重启消息的模块
		(state == SYSTEM_HALT) ? SYS_HALT : SYS_POWER_OFF, NULL);
	system_state = state;
	usermodehelper_disable();
	device_shutdown(); 关闭所有驱动设备
}

15. @Core.c (drivers\base)
/**
 * device_shutdown - call ->shutdown() on each device to shutdown.
 */
void device_shutdown(void)
{
	while (!list_empty(&devices_kset->list)) {
		dev = list_entry(devices_kset->list.prev, struct device,
				kobj.entry);
		if (dev->bus && dev->bus->shutdown) {
			if (1)
				dev_info(dev, "shutdown\n");
			dev->bus->shutdown(dev);
		} else if (dev->driver && dev->driver->shutdown) {
			if (1)
				dev_info(dev, "shutdown\n");
			dev->driver->shutdown(dev);
		}
}

16. @Syscore.c (drivers\base)
/**
 * syscore_shutdown - Execute all the registered system core shutdown callbacks.
 */
void syscore_shutdown(void)
{
	struct syscore_ops *ops;
	mutex_lock(&syscore_ops_lock);
	list_for_each_entry_reverse(ops, &syscore_ops_list, node)
		if (ops->shutdown) {
			if (initcall_debug)
				pr_info("PM: Calling %pF\n", ops->shutdown);
			ops->shutdown();
		}
	mutex_unlock(&syscore_ops_lock);
}

17. @Process.c (arch\arm\kernel)
/*
 * Power-off simply requires that the secondary CPUs stop performing any
 * activity (executing tasks, handling interrupts). smp_send_stop()
 * achieves this. When the system power is turned off, it will take all CPUs
 * with it.
 */
void machine_power_off(void)
{
	local_irq_disable();
	smp_send_stop();
	pr_emerg("machine_power_off, pm_power_off(%p)\n", pm_power_off);
	dump_stack();
	if (pm_power_off) 各个硬件平台的PMIC power off函数
		pm_power_off();
}

18. @Psci.c (arch\arm\kernel)	
static int psci_0_2_init(struct device_node *np)
{
pm_power_off = psci_sys_poweroff; 平台级别的power off函数
}

 

 

 

 

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值