Linux内核关机重启源码分析
来源:互联网 发布:淘宝客服忙不忙 编辑:程序博客网 时间:2024/05/01 06:14
Linux在PC上的关机和重启可能由两种行为引发,一是通过用户编程,一是系统自己产生的消息。用户和系统进行交互的方式也有两个,一个是系统调用:sys_reboot,另一个就是apm或acpi的设备文件,通过对其操作也可以使系统关机或者重启。
一、从reboot命令开始
reboot命令会执行系统调用来实现重启。我们在运行reboot时,会打印下面信息:
Restarting system.
这句话在kernel/sys.c的kernel_restart()函数中打印出来。
而调用kernel_restart函数的地方是,sys.c中的reboot系统调用宏定义中:
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
void __user *, arg)
{
……
lock_kernel();
switch (cmd) {
case LINUX_REBOOT_CMD_RESTART:
kernel_restart(NULL);
break;
……
kernel_restart函数实现如下:
void kernel_restart(char *cmd)
{
kernel_restart_prepare(cmd); //重启前,向其它部分发出重启的消息
if (!cmd)
printk(KERN_EMERG "Restarting system.\n");
else
printk(KERN_EMERG "Restarting system with command '%s'.\n", cmd);
machine_restart(cmd); //实际重启
}
EXPORT_SYMBOL_GPL(kernel_restart);
对于X86平台的machine_restart实现在arch/x86/kernel/reboot.c中:
void machine_restart(char *cmd)
{
machine_ops.restart(cmd);
}
其中,machine_ops定义和初始化如下:
struct machine_ops machine_ops = {
.power_off = native_machine_power_off,
.shutdown = native_machine_shutdown,
.emergency_restart = native_machine_emergency_restart,
.restart = native_machine_restart,
.halt = native_machine_halt,
#ifdef CONFIG_KEXEC
.crash_shutdown = native_machine_crash_shutdown,
#endif
};
可见,restart函数是native_machine_restart,其实现如下:
static void native_machine_restart(char *__unused)
{
printk("machine restart\n");
if (!reboot_force)
machine_shutdown();
machine_emergency_restart();
}
而native_machine_restart又调用了machine_emergency_restart函数,如下:
void machine_emergency_restart(void)
{
machine_ops.emergency_restart();
}
最终,实现X86重启的函数native_machine_emergency_restart如下:
static voidnative_machine_emergency_restart(void)
{
int i;
*((unsigned short *)__va(0x472)) = reboot_mode;
for (;;) {
/* Could also try the reset bit in the Hammer NB */
switch (reboot_type) {
case BOOT_KBD:
mach_reboot_fixups(); /* for board specific fixups */
for (i = 0; i < 10; i++) {
kb_wait();
udelay(50);
outb(0xfe, 0x64); /* pulse reset low */
udelay(50);
}
case BOOT_TRIPLE:
load_idt(&no_idt);
__asm__ __volatile__("int3");
reboot_type = BOOT_KBD;
break;
#ifdef CONFIG_X86_32
case BOOT_BIOS:
machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
reboot_type = BOOT_KBD;
break;
#endif
case BOOT_ACPI:
acpi_reboot();
reboot_type = BOOT_KBD;
break;
case BOOT_EFI:
if (efi_enabled)
efi.reset_system(reboot_mode ? EFI_RESET_WARM : EFI_RESET_COLD,
EFI_SUCCESS, 0, NULL);
reboot_type = BOOT_KBD;
break;
}
}
}
一般情况下,运行reboot命令,进入的是BOOT_KBD这个case,然后,运行到BOOT_TRIPLE这个case,对于下面这句话,
__asm__ __volatile__("int3");
本人找了N+1本书,发现这句话的作用是产生一个breakpoint异常。
而实际重启的实现是在BOOT_KBD这个case中的:
for (i = 0; i < 10; i++) {
kb_wait();
udelay(50);
outb(0xfe, 0x64); /* pulse reset low */
udelay(50);
}
对于outb(0xfe,0x64)原理,我也不清楚,ICH8芯片手册找了没找到,Intel 965北桥芯片手册也没找到,网上说:
在不通过bios进行重启的情况下,系统向端口0xfe写入数字0x64,这种重启的具体原理我还不大清楚,似乎是模拟了一次reset键的按下。
知道的XDJM们在评论中告知一声,谢谢。
二、APM和ACPI
acpi模块的相关源代码在linux/drivers/acpi/中,以后有时间将对其进行具体分析。
注意:本文基于linux-2.6.28和X86平台进行分析。
- Linux内核关机重启源码分析
- Linux 关机重启流程分析
- Linux 关机重启流程分析
- Linux关机重启流程分析
- Linux 关机重启流程分析
- Linux 关机重启流程分析
- Linux 关机重启流程分析
- Linux关机重启流程分析
- 内核层关机重启
- Linux 关机重启
- Linux关机重启停机(shutdown reboot halt)流程分析
- Android关机重启分析
- linux 关机/重启命令
- Linux 关机/重启命令
- Linux关机重启命令
- linux注销、关机、重启
- Linux 关机和重启
- Linux命令 关机/重启
- 本地计算机上的 MSSQLSERVER 服务启动后又停止了 问题分析
- 源码搜
- iOS文件管理 NSFileManager NSFileHandle
- Ubuntu中apt-get命令详解
- MPLab X 配置字的设置
- Linux内核关机重启源码分析
- 挑战编程:抛硬币赌博游戏【转】
- iBatis调用返回两个游标的存储过程处理方法
- TwoSat
- apple相关网址
- SQLite 第三版中的数据类型
- < Linux Kernel > Reference Counts
- 如何在 ESRI ArcMap 中打开谷歌卫星地图
- C++小结1