当前位置:   article > 正文

(android 关机/重启)Android关机/重启流程解析_performing low-level shutdown...

performing low-level shutdown...

refer:http://blog.csdn.net/leerobin83/article/details/7162751

目录(?)[-]

  1. public void reboot String reason
  2. --------------------------------上层空间--------------------------------
    1. frameworks/base/core/java/android/os/PowerManagerjava
    2. frameworks/base/core/java/android/os/IPowerManageraidl
    3. frameworks/base/services/java/com/androidserver/PowerManagerServicejava
    4. frameworks/base/services/java/com/androidserver/pm/ShutdownThreadjava
    5. frameworks/base/services/java/com/androidserver/PowerManagerServicejava
    6. frameworks/base/services/jni/com_android_server_PowerManagerServicecpp
    7. system/core/lib/cutils/android_rebootc
    8. bionic/libc/unistdre/bootc
  3. --------------------------------KERNEL域--------------------------------
    1. __reboot通过syscall来到内核
    2. kernelsysc
    3. 最终实现
  4. 关机怎么用(最终的总结:本质的调用)
  5. adb 测试重启命令(adb reboot recovery,charger,kpoc,bootloader,etc)
  6. 资料:

    https://developer.android.com/intl/zh-CN/reference/android/os/PowerManager.html
















--------------------------------Introduction--------------------------

         1. 在PowerManager的API文档中,给出了一个关机/重启接口:

        public void reboot (String reason)
         2. 对于这个接口的描述很简单,就是几句话。

                    接口的作用就是重启设备,而且,就算重启成功了也没有返回值。

                    需要包含REBOOT权限,也就是android.permission.REBOOT

                    唯一参数reason代表需要的特定重启模式,比如recovery,当然也可以为null。

--------------------------------上层空间--------------------------------

1.frameworks/base/core/java/android/os/PowerManager.java

  1. /**  
  2.  * Reboot the device.  Will not return if the reboot is 
  3.  * successful.  Requires the {@link android.Manifest.permission#REBOOT} 
  4.  * permission. 
  5.  * 
  6.  * @param reason code to pass to the kernel (e.g., "recovery") to 
  7.  *               request special boot modes, or null. 
  8.  */  
  9. public void reboot(String reason)  
  10. {     
  11.     try {  
  12.         mService.reboot(reason);  
  13.     } catch (RemoteException e) {  
  14.     }     
  15. }   

mService为IPowerManager Binder接口服务。
  1. /** 
  2.  * {@hide} 
  3.  */  
  4. public PowerManager(IPowerManager service, Handler handler)  
  5. {  
  6.     mService = service;  
  7.     mHandler = handler;  
  8. }  


2.frameworks/base/core/java/android/os/IPowerManager.aidl

  1. interface IPowerManager  
  2. {  
  3. ...  
  4. void reboot(String reason);  
  5. ...  
  6. }  

3.frameworks/base/services/java/com/android/server/PowerManagerService.java

  1. /**   
  2.  * Reboot the device immediately, passing 'reason' (may be null) 
  3.  * to the underlying __reboot system call.  Should not return. 
  4.  */  
  5. public void reboot(String reason)  
  6. {      
  7.     mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);  
  8.   
  9.     if (mHandler == null || !ActivityManagerNative.isSystemReady()) {  
  10.         throw new IllegalStateException("Too early to call reboot()");  
  11.     }      
  12.   
  13.     final String finalReason = reason;  
  14.     Runnable runnable = new Runnable() {  
  15.         public void run() {  
  16.             synchronized (this) {  
  17.                 ShutdownThread.reboot(getUiContext(), finalReason, false);  
  18.             }      
  19.   
  20.         }      
  21.     };     
  22.     // ShutdownThread must run on a looper capable of displaying the UI.  
  23.     mHandler.post(runnable);  
  24.   
  25.     // PowerManager.reboot() is documented not to return so just wait for the inevitable.  
  26.     synchronized (runnable) {  
  27.         while (true) {  
  28.             try {  
  29.                 runnable.wait();  
  30.             } catch (InterruptedException e) {   
  31.             }      
  32.         }      
  33.     }      
  34. }  

4.frameworks/base/services/java/com/android/server/pm/ShutdownThread.java

  1. /** 
  2.  * Request a clean shutdown, waiting for subsystems to clean up their 
  3.  * state etc.  Must be called from a Looper thread in which its UI 
  4.  * is shown. 
  5.  * 
  6.  * @param context Context used to display the shutdown progress dialog. 
  7.  * @param reason code to pass to the kernel (e.g. "recovery"), or null. 
  8.  * @param confirm true if user confirmation is needed before shutting down. 
  9.  */  
  10. public static void reboot(final Context context, String reason, boolean confirm) {  
  11.     mReboot = true;  
  12.     mRebootSafeMode = false;  
  13.     mRebootReason = reason;  
  14.     shutdownInner(context, confirm);  
  15. }  
       如上所叙述,这里说明是需要重启,且不是安全模式,重启参数为传递下来的reason,shutdownInner的confirm参数是用来设置是否有确认提示框的,通过reboot接口调用重启是没有的,为false。



        重启的实现在run()中,因为ShutdownThread是Thread的扩展,所以run会自动运行,如下。

 /**
     * Makes sure we handle the shutdown gracefully.
     * Shuts off power regardless of radio and bluetooth state if the alloted time has passed.
     */
    public void run() {
        checkShutdownFlow();
        while (mShutdownFlow == IPO_SHUTDOWN_FLOW) {
            stMgr.saveStates(mContext);
            stMgr.enterShutdown(mContext);
            running();
        }
        if (mShutdownFlow != IPO_SHUTDOWN_FLOW) {
            stMgr.enterShutdown(mContext);
            running();
        }
    }




public void running() {

  1.         if(sPreShutdownApi != null){
                try {
                    sPreShutdownApi.onPowerOff();
                } catch (RemoteException e) {
                    Log.e(TAG, "onPowerOff exception" + e.getMessage());
                }
            }else{
                Log.w(TAG, "sPreShutdownApi is null");
            }

            command = SystemProperties.get("sys.ipo.pwrdncap");

            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();
                }
            };
  2.     /* 
  3.      * Write a system property in case the system_server reboots before we 
  4.      * get to the actual hardware restart. If that happens, we'll retry at 
  5.      * the beginning of the SystemServer startup. 
  6.      */   
  7.     {     
  8.         String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : "");  
  9.         SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);  
  10.     }  
  11.   
  12.     /* 
  13.      * If we are rebooting into safe mode, write a system property 
  14.      * indicating so. 
  15.      */   
  16.     if (mRebootSafeMode) {  
  17.         SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");  
  18.     }  
  19.     ...  
  20.     rebootOrShutdown(mReboot, mRebootReason);  
  21. }   

         如上所叙述,在重启前会将重启原因写入sys.shutdown.requested,如果没有则为空,如果是安全模式还会将persist.sys.safemode置1,之后会进行一些关机前的预处理,关闭ActivityManager以及MountService,最终调用rebootOrShutdown进行关机操作。


======>>>>>>android2中的rebootOrShutdown

  1.     /** 
  2.      * Do not call this directly. Use {@link #reboot(Context, String, boolean)} 
  3.      * or {@link #shutdown(Context, boolean)} instead. 
  4.      * 
  5.      * @param reboot true to reboot or false to shutdown 
  6.      * @param reason reason for reboot 
  7.      */  
  8.     public static void rebootOrShutdown(boolean reboot, String reason) {  
  9.         if (reboot) {  
  10.             Log.i(TAG, "Rebooting, reason: " + reason);   
  11.             try {  
  12.                 PowerManagerService.lowLevelReboot(reason);  ///重启Reboot
  13.             } catch (Exception e) {  
  14.                 Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);  
  15.             }   
  16.         } else if (SHUTDOWN_VIBRATE_MS > 0) {  ///关机的时候需要震动,就是这里了 
  17.                                                                                //SHUTDOWN_VIBRATE_MS,默认的定义是500ms。
  18.             // vibrate before shutting down  
  19.             Vibrator vibrator = new SystemVibrator();  
  20.             try {  
  21.                 vibrator.vibrate(SHUTDOWN_VIBRATE_MS);  
  22.             } catch (Exception e) {  
  23.                 // Failure to vibrate shouldn't interrupt shutdown.  Just log it.  
  24.                 Log.w(TAG, "Failed to vibrate during shutdown.", e);  
  25.             }     
  26.                   
  27.             // vibrator is asynchronous so we need to wait to avoid shutting down too soon.  
  28.             try {  
  29.                 Thread.sleep(SHUTDOWN_VIBRATE_MS);  
  30.             } catch (InterruptedException unused) {  
  31.             }     
  32.         }     
  33.               
  34.         // Shutdown power  
  35.         Log.i(TAG, "Performing low-level shutdown...");  
  36.         PowerManagerService.lowLevelShutdown();直接关机Shutdown
  37.     }  
  38. }  
    如上所叙述,

            如果重启,则调用PowerManagerService的lowLevelReboot函数,参数就是传递下来的reason,稍后分析。    

            如果不是重启,即mReboot=false,那就是需要关机了,在shutdown函数中就能够知道。如下所示:

  1. /** 
  2.  * Request a clean shutdown, waiting for subsystems to clean up their 
  3.  * state etc.  Must be called from a Looper thread in which its UI 
  4.  * is shown. 
  5.  * 
  6.  * @param context Context used to display the shutdown progress dialog. 
  7.  * @param confirm true if user confirmation is needed before shutting down. 
  8.  */  
  9. public static void shutdown(final Context context, boolean confirm) {  
  10.     mReboot = false;  
  11.     mRebootSafeMode = false;  
  12.     shutdownInner(context, confirm);  
  13. }  

        如上所示,会有reboot 以及 shutdown的操作。

        但是在代码逻辑上看,无论如何,最后都会调用一下lowLevelShutdown函数,也就是关机。

         逻辑上,这里可能是个问题,但是实际中,如果重启操作能够调用成功的话,整个系统都重启了,后边的代码当然不可能执行到了。

======>>>>>>android4.4中的rebootOrShutdown

{ android 4.4中的rebootOrShutdown---解析

public static void rebootOrShutdown(boolean reboot, String reason) {
        if (reboot) {
            Log.i(TAG, "Rebooting, reason: " + reason);
            if ( (reason != null) && reason.equals("recovery") ) {
                delayForPlayAnimation();
            }
            try {
                PowerManagerService.lowLevelReboot(reason);
            } catch (Exception e) {
                Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);
            }
        } else if (SHUTDOWN_VIBRATE_MS > 0) {
            // vibrate before shutting down
            Vibrator vibrator = new SystemVibrator();
            try {
                vibrator.vibrate(SHUTDOWN_VIBRATE_MS);
            } 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);
            } catch (InterruptedException unused) {
            }
        }

        delayForPlayAnimation();
        // Shutdown power
        // power off auto test, don't modify
        Log.i(TAG, "Performing low-level shutdown...");
        //PowerManagerService.lowLevelShutdown();已经注释掉了
        //add your func: HDMI off
        //add for MFR
        try {
            if (ImHDMI == null)
                ImHDMI=MediatekClassFactory.createInstance(IHDMINative.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        ImHDMI.hdmiPowerEnable(false);

        //unmout data/cache partitions while performing shutdown

        SystemProperties.set("ctl.start", "shutdown");直接关机shutdown操作

        /* sleep for a long time, prevent start another service */
        try {
            Thread.currentThread().sleep(Integer.MAX_VALUE);
        } catch ( Exception e) {
            Log.e(TAG, "Shutdown rebootOrShutdown Thread.currentThread().sleep exception!");
        }
    }


}

          目光转回PowerManagerService 中进行的lowLevelReboot()调用。。。。

4.frameworks/base/services/java/com/android/server/PowerManagerService.java

  1. /**   
  2.  * Low-level function to reboot the device. 
  3.  * 
  4.  * @param reason code to pass to the kernel (e.g. "recovery"), or null. 
  5.  * @throws IOException if reboot fails for some reason (eg, lack of 
  6.  *         permission) 
  7.  */  
  8. public static void lowLevelReboot(String reason) throws IOException {  
  9.     nativeReboot(reason);  
  10. }    
  11.   
  12. /**   
  13.  * Low-level function turn the device off immediately, without trying 
  14.  * to be clean.  Most people should use 
  15.  * {@link com.android.server.pm.internal.app.ShutdownThread} for a clean shutdown. 
  16.  */  
  17. public static void lowLevelShutdown() {  
  18.     nativeShutdown();  
  19. }   

很熟悉的字样native,是JNI调用了:

  1. private static native void nativeShutdown();  
  2. private static native void nativeReboot(String reason) throws IOException; 


        ===>>>>>android 4.4 中的lowLevelShutdown  以及  lowLevelReboot

public static void lowLevelShutdown() {
        SystemProperties.set("sys.powerctl", "shutdown");直接关机
    }

    /**
     * Low-level function to reboot the device. On success, this function
     * doesn't return. If more than 5 seconds passes from the time,
     * a reboot is requested, this method returns.
     *
     * @param reason code to pass to the kernel (e.g. "recovery"), or null.
     */
    public static void lowLevelReboot(String reason) {
        if (reason == null) {
            reason = "";
        }
        SystemProperties.set("sys.powerctl", "reboot," + reason);///重启
        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

【注解:】

        关机流程中最后是通过修改Android属性进行关机操作(SystemProperties.java通过JNI调用访问系统属性)。

        当然我们也可以通过adb命令修改Android系统属性执行关机操作,例如adb shell setpro sys.powerctl shutdown。

         这里我们简单介绍下修改Android属性关机的原理或流程。

native_set()--->SystemProperties_set()

这是SystemProperties.java类中设置系统函数的方法。



5.frameworks/base/services/jni/com_android_server_PowerManagerService.cpp

  1. static JNINativeMethod gPowerManagerServiceMethods[] = {   
  2.     /* name, signature, funcPtr */  
  3.     ...  
  4.     { "nativeShutdown""()V",  
  5.             (void*) nativeShutdown },  
  6.     { "nativeReboot""(Ljava/lang/String;)V",  
  7.             (void*) nativeReboot },  
  8.     ...  
  9. };  

这两个好哥俩的实现也是在一起的:
  1. static void nativeShutdown(JNIEnv *env, jobject clazz) {  
  2.     android_reboot(ANDROID_RB_POWEROFF, 0, 0);  直接关机
  3. }  
  4.   
  5. static void nativeReboot(JNIEnv *env, jobject clazz, jstring reason) {  
  6.     if (reason == NULL) {  
  7.         android_reboot(ANDROID_RB_RESTART, 0, 0);  //无reboot reason的重启
  8.     } else {  
  9.         const char *chars = env->GetStringUTFChars(reason, NULL);  
  10.         android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars); //有reboot reason的重启
  11.         env->ReleaseStringUTFChars(reason, chars);  // In case it fails.  
  12.     }  
  13.     jniThrowIOException(env, errno);  
  14. }  

可以看到无论是关机还是重启,都是调用android_reboot来实现的,只是参数不一样而已。


6.system/core/libcutils/android_reboot.c

      int android_reboot(int cmd, int flags, char *arg)
{
    int ret;

    sync();
    remount_ro();

    switch (cmd) {
        case ANDROID_RB_RESTART://普通重启
            ret = reboot(RB_AUTOBOOT);
            break;

        case ANDROID_RB_POWEROFF:/直接关机
            ret = reboot(RB_POWER_OFF);
            break;

        case ANDROID_RB_RESTART2:
            ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,///有参数的重启直接走这里
                           LINUX_REBOOT_CMD_RESTART2, arg);
            break;

        default:
            ret = -1;
    }

    return ret;
}

        以reboot recovery为例,arg即为recovery,所在在第5步的时候会传入ANDROID_RB_RESTART2。

        接下来才是对参数的解析处理:

1)普通重启 ANDROID_RB_RESTART, reason = RB_AUTOBOOT;

2)关机 ANDROID_RB_POWEROFF, 无需reason,直接调用reboot进行关机;

3)带参数的特殊重启 ANDROID_RB_RESTART2, reason 将为默认值 -1

      注解1:在有的android版本里,这里又会出现一个#ifdef RECOVERY_PRE_COMMAND_CLEAR_REASON,如果定义了它,则无论上层传下来的参数是什么样的,最终都只是普通重启而已。定义它的方式是在BoardConfig.mk中加入TARGET_RECOVERY_PRE_COMMAND_CLEAR_REASON := true,应该有厂商会喜欢这么做的,毕竟除了普通重启,都可能带给用户一定的风险。最后会对reason进行一个检测,那么通过上边的分析,其实只有带参数的特殊重启才会为-1,而不等于-1的情况中有普通重启和关机,而关机已经自行解决了……所以,不等于-1的情况到了这里也只有普通重启了。最终这里就是区分普通重启与特殊重启的地方了。

      注解2: 这里再插入一个问题,其他的几个cmd都是什么值呢?答案在bionic/libc/include/sys/reboot.h中:

  1. #define RB_AUTOBOOT     LINUX_REBOOT_CMD_RESTART  
  2. #define RB_HALT_SYSTEM  LINUX_REBOOT_CMD_HALT  
  3. #define RB_ENABLE_CAD   LINUX_REBOOT_CMD_CAD_ON  
  4. #define RB_DISABLE_CAD  LINUX_REBOOT_CMD_CAD_OFF  
  5. #define RB_POWER_OFF    LINUX_REBOOT_CMD_POWER_OFF  

      而,LINUX_REBOOT_XXXX之类的在bionic/libc/kernel/common/linux/reboot.h中:
  1. #define LINUX_REBOOT_MAGIC1 0xfee1dead  
  2. #define LINUX_REBOOT_MAGIC2 672274793  
  3. /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */  
  4. #define LINUX_REBOOT_MAGIC2A 85072278  
  5. #define LINUX_REBOOT_MAGIC2B 369367448  
  6. #define LINUX_REBOOT_MAGIC2C 537993216  
  7. #define LINUX_REBOOT_CMD_RESTART 0x01234567  
  8. /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */  
  9. #define LINUX_REBOOT_CMD_HALT 0xCDEF0123  
  10. #define LINUX_REBOOT_CMD_CAD_ON 0x89ABCDEF  
  11. #define LINUX_REBOOT_CMD_CAD_OFF 0x00000000  
  12. #define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC  
  13. /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */  
  14. #define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4  
  15. #define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2  
  16. #define LINUX_REBOOT_CMD_KEXEC 0x45584543  
       至于为什么他们是这样奇怪的值这个问题,我只能说他们是magic number,魔法嘛,本来就是正常人不能够理解的,所以~~~放过他们吧,只要知道他们没有是-1的就OK啦。


       先来看reboot函数,按照往常的经验,reboot最终一定会调用到__reboot的。


7.bionic/libc/unistd/reboot.c   ///A:\v387-debug\my-ap\bionic\libc\bionic\reboot.c

  1. int reboot (int  mode)   
  2. {  
  3.     return __reboot( LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL );  
  4. }  

Bingo!果然是这样,如此说来reboot(reason) -> reboot(RB_AUTOBOOT) -> __reboot( LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART, NULL ),要是直接这样写多好~~~免得绕这一层了。

--------------------------------KERNEL域--------------------------------

8.__reboot通过syscall来到内核

这里用一些篇幅简要介绍syscall,以后遇到类似的东西更好追踪一些。

第七步中的__reboot在arm架构的实现是这样的(bionic/libc/arch-arm/syscalls/__reboot.S)

/home/tonylau/tony-workspace/v387-debug/my-ap/bionic/libc/arch-arm/syscalls/__reboot.S

  1. ENTRY(__reboot)  
  2.     .save   {r4, r7}   
  3.     stmfd   sp!, {r4, r7}  
  4.     ldr     r7, =__NR_reboot  
  5.     swi     #0    
  6.     ldmfd   sp!, {r4, r7}  
  7.     movs    r0, r0  
  8.     bxpl    lr    
  9.     b       __set_syscall_errno  
  10. END(__reboot)  

      可以看出来,这里将__reboot的实现映射到了__NR_reboot, 而在bionic/libc/sys/linux-syscalls.h((/home/tonylau/tony-workspace/v387-debug/my-ap/prebuilts/ndk/8/platforms/android-4/arch-arm/usr/include/sys/linux-syscalls.h))能够找到:
  1. #define __NR_reboot                       (__NR_SYSCALL_BASE + 88)  

        其被指定了一个固定的偏移量,在被调用的时候就是通过这个偏移量去内核中寻找对应的入口的,由此可见,内核中一定有着相同的定义,否则将不能成功调用。内核中对syscall偏移量的定义在内核源码中的arch/arm/include/asm/unistd.h,相关信息完全一致。

        已经找到了内核中的对应映射,那么下一步就要去找寻真正的实现函数了,在include/asm-generic/unistd.h(/home/tonylau/tony-workspace/v387-debug/my-ap/prebuilts/ndk/9/platforms/android-4/arch-arm/usr/include/asm/unistd.h)中可以找到内核对__NR_reboot的syscall函数映射,即

  1. /* kernel/sys.c */  
  2. #define __NR_setpriority 140  
  3. __SYSCALL(__NR_setpriority, sys_setpriority)  
  4. #define __NR_getpriority 141  
  5. __SYSCALL(__NR_getpriority, sys_getpriority)  
  6. #define __NR_reboot 142  
  7. __SYSCALL(__NR_reboot, sys_reboot)  

同时,能够发现如此温馨的一幕,内核已经指引我们下一步该去哪里寻找sys_reboot,即kernel/sys.c。


9.kernel/sys.c

       在进入这个文件前,我们先去include/linux/syscalls.h中查看一下sys_reboot的定义:

  1. asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd,  
  2.                 void __user *arg);  

与__reboot的调用参数一致。

          进入sys.c文件后,并没有找到名为sys_reboot的函数,而通过仔细查找,发现一个很有趣的函数,其定义为SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg),对比__reboot的参数,能够符合。究竟是不是这个函数?

         同样在include/linux/syscalls.h文件中,能够找到这样几个定义:

  1. #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)  
  2. #define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)  
  3. #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)  
  4. #define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)  
  5. #define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)  
  6. #define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)  
  7. ...  
  8.   
  9. #define SYSCALL_DEFINEx(x, sname, ...)              \  
  10.     __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)  
  11. ...  
  12.   
  13. #define __SYSCALL_DEFINEx(x, name, ...)                 \  
  14.     asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__))  

整合后等价于:
  1. #define SYSCALL_DEFINE4(name, ...) \  
  2.     asmlinkage long sys##_name(__SC_DECL##4(__VA_ARGS__))  

        这样就不难看出,SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg)就是sys_reboot,也就是上层调用的__reboot的最终实现。函数实现如下:
  1. /* 
  2.  * Reboot system call: for obvious reasons only root may call it, 
  3.  * and even root needs to set up some magic numbers in the registers 
  4.  * so that some mistake won't make this reboot the whole machine. 
  5.  * You can also set the meaning of the ctrl-alt-del-key here. 
  6.  * 
  7.  * reboot doesn't sync: do that yourself before calling this. 
  8.  */  
  9. SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,  
  10.         void __user *, arg)  
  11. {  
  12.     char buffer[256];  
  13.     int ret = 0;  
  14.   
  15.     /* We only trust the superuser with rebooting the system. */  
  16.     if (!capable(CAP_SYS_BOOT))  ///首先会检测权限问题,只有超级用户才可以执行重启系统的操作
  17.         return -EPERM;        /否则将返回权限错误。对应的权限列表在include/linux/capability.h中,重启操作为22
  18.   
  19.     /* For safety, we require "magic" arguments. */  //随后对magic number进行了校验
  20.     if (magic1 != LINUX_REBOOT_MAGIC1 ||       如果数据传输过程中没有发生错误的话,
  21.                                                            这里也当然不会有问题,所以只是一个安全性校验,基本不会发生错误。
  22.         (magic2 != LINUX_REBOOT_MAGIC2 &&  
  23.                     magic2 != LINUX_REBOOT_MAGIC2A &&  
  24.             magic2 != LINUX_REBOOT_MAGIC2B &&  
  25.                     magic2 != LINUX_REBOOT_MAGIC2C))  
  26.         return -EINVAL;  
  27.   
  28.     /* Instead of trying to make the power_off code look like 
  29.      * halt when pm_power_off is not set do it the easy way. 
  30.      */  
  31.     if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)  
  32.         cmd = LINUX_REBOOT_CMD_HALT;  ///之后有一个很有趣的检查,如果用户要求关机,而pm_power_off为空的话,就把用户的关机命令转换为挂起:
  33.   
  34.     mutex_lock(&reboot_mutex);  
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/945219
推荐阅读
相关标签
  

闽ICP备14008679号