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个函数:
- 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停下来,以防止系统挂死。
- 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的而不是第二个第三个,主要原因一是为了简单,二是防止在重启时再有什么任务迁移。
- 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则在此处调用。
- 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
};
可以根据重启的不同场景,然后传递对应的重启原因。 - 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停下来,然后调用重启接口重启系统。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
