Kernel函数解析之kernel_restart

该函数实现在kernel/reboot.c中,主要功能为重新启动kernel,比如发现kernel进入到了一个异常场景,此时我想重启kernel,那么该函数就可以调用。


   
     
     
     
     
  1. void kernel_restart( char *cmd)
  2. {
  3. kernel_restart_prepare(cmd);
  4. migrate_to_reboot_cpu();
  5. syscore_shutdown();
  6. if (!cmd)
  7. pr_emerg( "Restarting system\n");
  8. else
  9. pr_emerg( "Restarting system with command '%s'\n", cmd);
  10. kmsg_dump( KMSG_DUMP_SHUTDOWN);
  11. machine_restart(cmd);
  12. }

那么接下来 我们解析下该函数的实现过程,该函数中,总共调用了5个函数:

  1. kernel_restart_prepare(cmd)
    
         
           
           
           
           
    1. void kernel_restart_prepare( char *cmd)
    2. {
    3. blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
    4. system_state = SYSTEM_RESTART;
    5. usermodehelper_disable();
    6. device_shutdown();
    7. }

    主要功能为回调注册到reboot_notifier_list链表中的回调函数,因为有部分模块,需要在重启系统前做一些模块相关的工作,举个简单的例子,比如系统要重启时edma正在搬移数据,那么回调后可以把EDMA停下来,以防止系统挂死。

  2. migrate_to_reboot_cpu();
    
         
           
           
           
           
    1. void migrate_to_reboot_cpu( void)
    2. {
    3. /* The boot cpu is always logical cpu 0 */
    4. int cpu = reboot_cpu;
    5. cpu_hotplug_disable();
    6. /* Make certain the cpu I'm about to reboot on is online */
    7. if (! cpu_online(cpu))
    8. cpu = cpumask_first(cpu_online_mask);
    9. /* Prevent races with other tasks migrating this task */
    10. current->flags |= PF_NO_SETAFFINITY;
    11. /* Make certain I only run on the appropriate processor */
    12. set_cpus_allowed_ptr(current, cpumask_of(cpu));
    13. }

    该函数主要是把当前调用重启接口的任务,绑定到固定的一个CPU上,通常为当前online的序号排第一的CPU。此处不用纠结为什么绑定到第一个online的而不是第二个第三个,主要原因一是为了简单,二是防止在重启时再有什么任务迁移。

  3. syscore_shutdown()
    
         
           
           
           
           
    1. /**
    2. * syscore_shutdown - Execute all the registered system core shutdown callbacks.
    3. */
    4. void syscore_shutdown( void)
    5. {
    6. struct syscore_ops *ops;
    7. mutex_lock(&syscore_ops_lock);
    8. list_for_each_entry_reverse(ops, &syscore_ops_list, node)
    9. if (ops->shutdown) {
    10. if (initcall_debug)
    11. pr_info( "PM: Calling %pS\n", ops->shutdown);
    12. ops->shutdown();
    13. }
    14. mutex_unlock(&syscore_ops_lock);
    15. }

    回调所有注册syscore shutdown回调的回调函数,通常注册syscore的回调有3个:suspend\resume\shutdown,其中suspend和resume在低功耗流程中调用,shutdown则在此处调用。

  4. kmsg_dump(KMSG_DUMP_SHUTDOWN);

    回调注册到dump_list中的dump回调,注册的模块可能会保存一些自己关心的数据。

    在这里也简单说下传参:

    enum kmsg_dump_reason {

           KMSG_DUMP_UNDEF,

           KMSG_DUMP_PANIC,

           KMSG_DUMP_OOPS,

           KMSG_DUMP_EMERG,

           KMSG_DUMP_SHUTDOWN,

           KMSG_DUMP_MAX

    };

    可以根据重启的不同场景,然后传递对应的重启原因。
  5. machine_restart(cmd);
    
         
           
           
           
           
    1. void machine_restart( char *cmd)
    2. {
    3. local_irq_disable();
    4. smp_send_stop();
    5. if (arm_pm_restart)
    6. arm_pm_restart(reboot_mode, cmd);
    7. else
    8. do_kernel_restart(cmd);
    9. /* Give a grace period for failure to restart of 1s */
    10. mdelay( 1000);
    11. /* Whoops - the platform was unable to reboot. Tell the user! */
    12. printk( "Reboot failed -- System halted\n");
    13. while ( 1);
    14. }

    函数实现在arch/arm/kernel/reboot.c中,我们首先可以看到,复位cpu会通过smp_send_stop接口把其他cpu停下来,然后调用重启接口重启系统。

你可能感兴趣的:(android,linux内核,linux,android)