在 Android 下,
我们在命令行中敲入 reboot 后系统的重启首先是执行的 reboot 这个
应用程序。这是一个比较简单的小程序,其源码在
代码如下:
1 if
if(poweroff)
2 ret
system/core/toolbox/reboot.c,主要的
=
__reboot(LINUX_REBOOT_MAGIC1,
LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_POWER_OFF, NULL);
3
else if
if(argc > optind)
ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2,
4
argv[optind]);
5
else
ret = reboot(RB_AUTOBOOT);
6
这 边 都 是 通 过 系 统 调 用 进 入 内 核 的 , LINUX_REBOOT_MAGIC1 和
LINUX_REBOOT_MAGIC2 是两个幻数。进入 kernel/sys.c 中
7
/*
8 * Reboot system call: for obvious reasons only root may call it,
9 * and even root needs to set up some magic numbers in the registers
10 * so that some mistake won't make this reboot the whole machine.
11 * You can also set the meaning of the ctrl-alt-del-key here.
12 *
13 * reboot doesn't sync: do that yourself before calling this.
14 */
15 SYSCALL_DEFINE4(reboot, int magic1, int magic2, unsigned int cmd,
int,
int,
int,
16
void __user *, arg)
17 {
18 char buffer[256];
19 int ret = 0;
20
21
/* We only trust the superuser with rebooting the system. */
22
if (!capable(CAP_SYS_BOOT))
return -EPERM;
23
24
25 /* For safety, we require "magic" arguments. */
26 if (magic1 != LINUX_REBOOT_MAGIC1 ||
(magic2 != LINUX_REBOOT_MAGIC2 &&
27
magic2 != LINUX_REBOOT_MAGIC2A &&
28
magic2 != LINUX_REBOOT_MAGIC2B &&
29
magic2 != LINUX_REBOOT_MAGIC2C))
30
return -EINVAL;
31
32
33 /* Instead of trying to make the power_off code look like
34 * halt when pm_power_off is not set do it the easy way.
35 */
36
37
if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
cmd = LINUX_REBOOT_CMD_HALT;
38
39 mutex_lock(&reboot_mutex);
40 switch (cmd) {
41 case LINUX_REBOOT_CMD_RESTART:
42 kernel_restart(NULL);
43 break
break;
44
45
case LINUX_REBOOT_CMD_CAD_ON:
46 C_A_D = 1;
47 break
break;
48
49
case LINUX_REBOOT_CMD_CAD_OFF:
50 C_A_D = 0;
51 break
break;
52
53
case LINUX_REBOOT_CMD_HALT:
54 kernel_halt();
55 do_exit(0);
56 panic("cannot halt");
57
58
case LINUX_REBOOT_CMD_POWER_OFF:
59 kernel_power_off();
60 do_exit(0);
61 break
break;
62
63
64
65
case LINUX_REBOOT_CMD_RESTART2:
if (strncpy_from_user(&buffer[0], arg, sizeof
sizeof(buffer) - 1) < 0) {
ret = -EFAULT;
break
break;
66
67 }
68 sizeof
buffer[sizeof
sizeof(buffer) - 1] = '\0';
69
70 kernel_restart(buffer);
71 break
break;
72
73 #ifdef CONFIG_KEXEC
74 case LINUX_REBOOT_CMD_KEXEC:
75 ret = kernel_kexec();
76 break
break;
77 #endif
78
79 #ifdef CONFIG_HIBERNATION
case LINUX_REBOOT_CMD_SW_SUSPEND:
80
81 ret = hibernate();
82 break
break;
83 #endif
84
default
default:
85
86 ret = -EINVAL;
87 break
break;
88 }
89 mutex_unlock(&reboot_mutex);
90 return ret;
91 }
我们通过命令行敲 reboot 的话进入的是 LINUX_REBOOT_CMD_RESTART 这个分支,可以
看到接下来会调用 kernel_restart(NULL);
92 /**
93 * kernel_restart - reboot the system
94 * @cmd: pointer to buffer containing command to execute for restart
95 *
96 *
97 * Shutdown everything and perform a clean reboot.
98 * This is not safe to call in interrupt context.
99 */
or %NULL
char
100 void kernel_restart(char *cmd)
101 {
102
103
104
kernel_restart_prepare(cmd);
if (!cmd)
printk(KERN_EMERG "Restarting system.\n");
105
else
printk(KERN_EMERG "Restarting system with command '%s'.\n", cmd);
106
107 kmsg_dump(KMSG_DUMP_RESTART);
108 machine_restart(cmd);
109 }
这个函数里面会打印出我们常看到的 log,Restarting system.
kernel_restart_prepare(cmd);里会去调用设备的 shutdown 接口,去 power off 设备,并且发送
SYS_RESTART 的广播,
char
110 void kernel_restart_prepare(char *cmd)
111 {
112 blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
113 system_state = SYSTEM_RESTART;
114 device_shutdown();
115 sysdev_shutdown();
116 }
接着执行 machine_restart(cmd);我们会调到 arch/x86/kernel/reboot.c 中,
这里需要知道一个 ops
117 struct machine_ops machine_ops = {
118 .power_off = native_machine_power_off,
119 .shutdown = native_machine_shutdown,
120 .emergency_restart = native_machine_emergency_restart,
121 .restart = native_machine_restart,
122 .halt = native_machine_halt,
123 #ifdef CONFIG_KEXEC
124
.crash_shutdown = native_machine_crash_shutdown,
125 #endif
126 };
machine_restart 就是执行这行这里的 native_machine_restart
char
127 static void native_machine_restart(char *__unused)
128 {
129
130
printk("machine restart\n");
131
if (!reboot_force) {
132 printk("native_machine_restart reboot_force:%d\n", reboot_force);
133 machine_shutdown();
134 }
135 __machine_emergency_restart(0);
136 }
machine_shutdown(); 中 执 行 一 些
__machine_emergency_restart(0);
shutdown
工 作 , 重 启 的 工 作 在
int
137 static void __machine_emergency_restart(int emergency)
138 {
139 reboot_emergency = emergency;
140 machine_ops.emergency_restart();
141 }
调用 ops 中的 emergency_restart
void
142 static void native_machine_emergency_restart(void
void)
143 {
144
int i;
145
146
147
if (reboot_emergency)
emergency_vmx_disable_all();
148
149
tboot_shutdown(TB_SHUTDOWN_REBOOT);
150
151 /* Tell the BIOS if we want cold or warm reboot */
152 *((unsigned short *)__va(0x472)) = reboot_mode;
153
154
for (;;) {
155 /* Could also try the reset bit in the Hammer NB */
156 switch (reboot_type) {
157 case BOOT_KBD:
158
mach_reboot_fixups(); /* for board specific fixups */
159
160 for (i = 0; i < 10; i++) {
161 printk("%d\n", i);
162 kb_wait();
163 udelay(50);
164 outb(0xfe, 0x64); /* pulse reset low */
udelay(50);
165
166
}
167
168
case BOOT_TRIPLE:
169
170
load_idt(&no_idt);
171
172
__asm__ __volatile__("int3");
173
174 reboot_type = BOOT_KBD;
175 break
break;
176
177 #ifdef CONFIG_X86_32
178
case BOOT_BIOS:
179 machine_real_restart(jump_to_bios, sizeof
sizeof(jump_to_bios));
180 reboot_type = BOOT_KBD;
181
break
break;
182 #endif
183
184
case BOOT_ACPI:
185
186 acpi_reboot();
187 reboot_type = BOOT_KBD;
188 break
break;
189
190
case BOOT_EFI:
191
192
193
if (efi_enabled)
efi.reset_system(reboot_mode ?
194 EFI_RESET_WARM :
195 EFI_RESET_COLD,
196 EFI_SUCCESS, 0, NULL);
197 reboot_type = BOOT_KBD;
198 break
break;
199
200
case BOOT_CF9:
201
202 port_cf9_safe = true
true;
203 /* fall through */
204
205
case BOOT_CF9_COND:
206
207
208
if (port_cf9_safe) {
u8 cf9 = inb(0xcf9) & ~6;
209
210 outb(cf9|2, 0xcf9); /* Request hard reset */
211 udelay(50);
212 outb(cf9|6, 0xcf9); /* Actually do the reset */
213 udelay(50);
214 }
215 reboot_type = BOOT_KBD;
216 break
break;
}
217
}
218
219 }
这边就是重启的最后部分了,默认的是通过 BOOT_KBD 方式重启的,这种方式是
通过键盘控制器去模拟按下键盘上的 reset 键来重启的,往 0x64 端口中写 0xfe 即可,然后
系统会在__asm__ __volatile__("int3");中中断。
int3 是一个 breakpoint,
用来使程序停止在这,
等待重启。
这里再说下,通过 cf9来重启,用注释来解释 Use the so-called "PCI reset register",
CF9,通过这个寄存器可以使系统 hard reset。
对于上面的一些重启方式,
我将在下一篇文章里去介绍他们的用法,
以及我在调试
reboot 中遇到的一些问题,这篇文章主要就是分析一下 reboot 的流程。
同样,附一张流程图:

更多相关文章

  1. python服务程序(调用摄像头查看视频和识别二维码)+ Android(安卓)
  2. android小注意
  3. Android学习之Service
  4. Android(安卓)短信模块分析(三) MMS入口分析
  5. RK3399 Android7.1 编译
  6. android浏览器开发小技巧集锦
  7. android Activity的onPause()与onResume()
  8. Android中AsyncTask的源码分析以及实例
  9. Android(安卓)四种启动方式个人理解简洁表达

随机推荐

  1. Android避免应用出现在最近使用APP列表里
  2. Android绘图之ComposeShader,PorterDuff.m
  3. Android中CoordinatorLayout(协调布局)的
  4. windows下配置安卓开发环境
  5. 多图片上传Android,服务器端实现
  6. Android Setting 设置项添加到快速搜索
  7. 【Android】查看程序每个方法所花费的时
  8. [android]寫一個system/bin 下的可執行文
  9. adb命令(不断补充)
  10. H5调用原生APP的js方法