Linux内核panic函数中__crash_kexec出现多次,请详细描述它的执行逻辑
时间: 2024-05-20 16:17:08 浏览: 196
在Linux内核中,panic函数是一种用于处理致命错误的机制。当内核遇到无法恢复的错误时,它会调用panic函数,此时内核会停止运行并输出错误信息。__crash_kexec是panic函数中的一个重要组成部分,它用于在系统崩溃时进行内核转储。
__crash_kexec函数的执行逻辑如下:
1. 首先,__crash_kexec会检查是否已经在进行内核转储操作。如果是,则直接退出函数。
2. 如果没有在进行内核转储操作,则将转储标志设置为真,以防止重复转储。
3. 接下来,__crash_kexec会调用crash_kexec函数,该函数会执行内核转储操作。这包括保存当前内核的状态和数据,以便后续分析和调试。
4. 内核转储完成后,__crash_kexec会将转储标志设置为假,并调用panic_restart函数。该函数将重启系统,以便在系统重新启动后进行分析和调试。
总之,__crash_kexec函数是Linux内核panic函数的重要组成部分,它用于在系统崩溃时进行内核转储,并且能够保证转储操作只执行一次。
相关问题
Linux内核的__crash_kexec函数的作用,逐行对源码进行注释
__crash_kexec函数是Linux内核中的一个函数,用于在系统崩溃时进行重启。下面是对该函数的源码逐行注释:
```c
void __crash_kexec(struct pt_regs *regs)
{
struct resource *res;
unsigned long flags;
const char *s;
int i;
unsigned long kexec_flags = (unsigned long)panic_timeout;
```
定义了一些变量,其中kexec_flags存储了panic_timeout的值,该值会在后面被用于设置kexec的一些标志。
```c
if (regs) {
printk(KERN_EMERG "Kernel panic - not syncing: ");
print_modules();
print_ip_sym(regs->ip);
dump_trace(regs, NULL);
} else {
printk(KERN_EMERG "Kernel panic - not syncing: Attempted to kill init!\n");
}
```
如果regs不为NULL,说明系统崩溃的原因是一个内核错误,需要打印一些错误信息。否则,说明试图kill init进程导致崩溃,需要打印“Attempted to kill init!”的错误信息。
```c
/*
* We may have crashed before we've had a chance to initialize
* the console, so be prepared for this.
*/
console_lock();
if (console_may_schedule())
panic_print = 1;
console_unlock();
```
由于在发生崩溃之前,可能还没有初始化控制台,所以需要在这里进行初始化。
```c
smp_send_stop();
local_irq_disable();
local_fiq_disable();
```
停止其他CPU的调度,并禁用本地中断和快速中断。
```c
if (regs) {
bad_mode(regs);
dump_instr(regs, NULL);
}
```
如果regs不为NULL,说明有内核错误,需要调用bad_mode函数和dump_instr函数来打印一些错误信息。
```c
/* Stop the machine */
machine_shutdown();
```
停止机器运行。
```c
/*
* Save the panic record before unmapping the kernel memory,
* which we are about to do. This is necessary because the
* panic record is stored in kernel memory.
*/
save_panic(__FILE__, __LINE__, __func__, "Crash_kexec");
```
保存崩溃记录。
```c
/* Free all unused memory */
free_unused_memmap();
free_initmem();
free_initrd_mem();
free_all_bootmem();
free_all_pages();
```
释放所有未使用的内存。
```c
/*
* Turn off the caches to try to make sure that everything
* written so far is flushed to memory.
*/
flush_cache_all();
```
关闭缓存以确保所有写入的数据都被刷新到内存中。
```c
/*
* Unmap kernel memory.
*/
unmap_kernel_range((unsigned long)end, 0xffffffff - PAGE_OFFSET);
```
取消内核内存的映射。
```c
/* Release resources */
release_resource(&root_resource);
for (i = 0; i < MAX_IORESOURCES; i++)
release_resource(&ioport_resource[i]);
for (i = 0; i < MAX_RESOURCE_TYPE; i++) {
res = resource_list[i].next;
while (res != &resource_list[i]) {
release_resource(res);
res = res->next;
}
}
```
释放资源。
```c
/*
* Try to set up kexec to reboot into a crash kernel.
* If that fails, just reboot directly.
*/
flags = kexec_flags | KEXEC_RESTART;
s = "kexec";
if (kexec_load(flags, NULL, NULL) < 0) {
flags = kexec_flags | KEXEC_PRESERVE_RTC | KEXEC_ON_CRASH;
if (kexec_load(flags, NULL, NULL) < 0) {
s = "reboot";
panic_blink();
machine_restart(s);
}
}
```
尝试设置kexec以重启到一个崩溃内核。如果失败,则直接重启。
```c
/*
* If we get here, kexec has been set up successfully.
* Just jump to the new kernel.
*/
kexec_do_shutdown(s);
}
```
如果成功,则跳转到新内核。
Linux 内核kexec_should_crash函数都被那些函数调用了
在Linux内核中,kexec_should_crash函数被以下函数调用:
1. panic()函数:在内核遇到严重错误时,该函数会触发系统崩溃并调用kexec_should_crash函数。
2. oops_end()函数:当内核发生oops(意外情况)时,该函数会结束oops并调用kexec_should_crash函数。
3. die()函数:该函数在内核遇到致命错误时会触发系统崩溃并调用kexec_should_crash函数。
4. do_exit()函数:当进程退出时,该函数可能会调用kexec_should_crash函数,以确定是否应该在退出时触发系统崩溃。
总之,kexec_should_crash函数主要用于确定是否应该在内核遇到严重错误时触发系统崩溃,并且被多个函数调用以实现该功能。
阅读全文