Android系统关机的全流程解析

2019-12-10 19:02:04刘景俊

但是细心的朋友可能会发现这里有一个restart_reason,这个并不是传递下来的参数。事实上,这个值已经在之前kernel_restart_prepare(cmd)的时候就已经设置好了。

void kernel_restart_prepare(char *cmd) 
{   
  blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); 
  system_state = SYSTEM_RESTART; 
  usermodehelper_disable(); 
  device_shutdown(); 
  syscore_shutdown(); 
} 

就是blocking_notifier机制,这个操作在之前的shutdown关机操作中也有,且是同一个list,都是reboot_notifier_list。也很容易理解,就是将注册在reboot_notifier_list上的函数传入相关参数后执行,作为了解,看一下具体是怎么使用的:(arch/arm/mach-msm/pm2.c)

static int msm_reboot_call 
  (struct notifier_block *this, unsigned long code, void *_cmd) 
{   
  if ((code == SYS_RESTART) && _cmd) { 
    char *cmd = _cmd; 
    if (!strcmp(cmd, "bootloader")) { 
      restart_reason = 0x77665500; 
    } else if (!strcmp(cmd, "recovery")) { 
      restart_reason = 0x77665502; 
    } else if (!strcmp(cmd, "eraseflash")) { 
      restart_reason = 0x776655EF; 
    } else if (!strncmp(cmd, "oem-", 4)) { 
      unsigned code = simple_strtoul(cmd + 4, 0, 16) & 0xff; 
      restart_reason = 0x6f656d00 | code; 
    } else { 
      restart_reason = 0x77665501;  
    }   
  }     
  return NOTIFY_DONE; 
}       
     
static struct notifier_block msm_reboot_notifier = { 
  .notifier_call = msm_reboot_call, 
}; 
 
... 
 
static int __init msm_pm_init(void) 
{ 
... 
  register_reboot_notifier(&msm_reboot_notifier); 
... 
} 

OK,万事大吉,在kernel_restart_prepare的时候msm_reboot_call会被首先调用,这个函数的作用就是根据用户命令给restart_reason赋值,从而在之后调用msm_pm_restart的时候使用。这里我们发现在reboot的时候可以带的参数不仅有recovery,bootloader,还有eraseflash和oem-???,字面上看应该是用来擦除ROM和解锁之类的操作了。