Kernel函数解析之kernel_restart

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

void kernel_restart(char *cmd)
{kernel_restart_prepare(cmd);migrate_to_reboot_cpu();syscore_shutdown();if (!cmd)pr_emerg("Restarting system\n");elsepr_emerg("Restarting system with command '%s'\n", cmd);kmsg_dump(KMSG_DUMP_SHUTDOWN);machine_restart(cmd);
}

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

  1. 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();
    }
    

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

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

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

  3. syscore_shutdown()
    /*** 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 %pS\n", ops->shutdown);ops->shutdown();}mutex_unlock(&syscore_ops_lock);
    }
    

    回调所有注册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);
    void machine_restart(char *cmd)
    {local_irq_disable();smp_send_stop();if (arm_pm_restart)arm_pm_restart(reboot_mode, cmd);elsedo_kernel_restart(cmd);/* Give a grace period for failure to restart of 1s */mdelay(1000);/* Whoops - the platform was unable to reboot. Tell the user! */printk("Reboot failed -- System halted\n");while (1);
    }
    

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


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部