前言:
有的时候,看到panic了,但是最后一次访问的backtrace有点长,一个屏幕内的log非常短,刚好错过了关键的backtrace。。。
分析:
1,patch
作者写了一个patch,方便把kmsg信息保存到文件中,下次启动可以查看:
修改linux-4.4/kernel/panic.c文件,增加函数:
#ifdef CONFIG_PRINTK
void dump_kmsg_to_file(void)
{
struct file *fkmsg = NULL;
struct file *ffile = NULL;
loff_t pos_kmsg = 0;
loff_t pos_file = 0;
int open_fflag = O_CREAT | O_RDWR | O_NOFOLLOW | O_SYNC;
char *buf = NULL;
size_t size = PAGE_SIZE;
size_t ret = 0;
const char __user *p;
mm_segment_t old_fs;
pr_emerg("trigger dump kmsg\n");
fkmsg = filp_open("/dev/kmsg", O_RDONLY, 0600);
if (fkmsg == NULL) {
pr_emerg("open /dev/ksmg fail\n");
goto out;
}
//(void) sys_unlink((const char __user *)"/var/KDUMPMSG");
ffile = filp_open("/var/KDUMPMSG", open_fflag, 0600);
if (ffile == NULL) {
pr_emerg("open /dev/ksmg fail\n");
goto close_fkmsg;
}
buf = vmalloc(size);
if (buf == NULL) {
pr_emerg("vmalloc fail\n");
goto close_ffile;
}
pr_emerg("start dump kmsg\n");
old_fs = get_fs();
set_fs(get_ds());
p = (__force const char __user *)buf;
fkmsg->f_pos = 0;
ffile->f_pos = 0;
while ((ret = __vfs_read(fkmsg, p, size, &pos_kmsg)) > 0) {
int n = 0;
fkmsg->f_pos = pos_kmsg;
while (ret) {
n = __vfs_write(ffile, p, ret, &pos_file);
if (n <= 0) {
pr_emerg("write log fail\n");
goto free_buf;
}
ffile->f_pos = pos_file;
ret -= n;
}
}
free_buf:
set_fs(old_fs);
if (buf)
kvfree(buf);
close_ffile:
if (ffile)
filp_close(ffile, NULL);
close_fkmsg:
if (fkmsg)
filp_close(fkmsg, NULL);
out:
return;
}
#endif /*#ifdef CONFIG_PRINTK*/
在pr_emerg("Kernel panic - not syncing: %s\n", buf);函数后面调用dump_kmsg_to_file();即可。