修改linux內核代碼或者內核模塊的時候,搞不好就會造成linux死機崩潰,crash死機后/var/log/kern.log里面不會有任何異常信息記錄。這時候kdump就會派上用場了,網上kdump的中英文介紹資料很多,但是很多都是基於系統自帶的linux進行說明的,這里記錄一下在新編譯的內核上使用kdump遇到的問題
1、首先使用ubuntu的config文件編譯的內核可以使用kdump
2、在上面的config文件后打開內核編譯的DEBUG_INFO選項,編譯安裝內核后,結果kdmup不起作用,crash后電腦直接卡死沒反應,有下面幾個現象
通過service --status-all查看,kdump服務成功啟動
通過kdump-config show 查看,kdump not ready。
重新啟動kdump服務。提示啟動成功,但是查看/var/log/syslog,看到有提示"Could not find a free area of memory of xxxxx",kdump預留內存不足,通過/proc/iomem查看已經預留了crash memory,但是預留的crash memory與syslog中提示的內存非常接近
重新啟動筆記本,在grub命令行編輯啟動命令,設置crash memory為256M,之前grub配置文件中為128M,重啟后,發現kdump服務ok,通過kdump-config show查看kdump 也是ready狀態。
通過echo c > /proc/sysrq-trigger觸發內核崩潰,看到kdump有響應,但是並不會重啟筆記本,也不會記錄crash信息
3、既然沒有配置DEBUG_INFO時候編譯的內核可以kdump,配置DEBUG_INFO后編譯的內核反而不能kdump,那么在安裝嘗試把DEBUG信息去掉
objcopy --strip-debug ./vmlinux.o (建議先備份vmlinux.o)
make modules_installs INSTALL_MOD_STRIP=1 install
上面兩條命令一個是把內核中的debug信息去掉,另外一個命令則是在安裝內核模塊的時候,同樣把內核模塊的debug info去掉,INSTALL_MOD_STRIP這個參數實際上就是從內核makefile中找到的,INSTALL_MOD_STRIP在makefile中就是控制strip-debug是否使能的。
4、經過上面把內核以及內核模塊的調試信息去掉后,確認kdump可以正常使用了
root@Inspiron:/home/lybxin# crash doc/ubuntu-compile/vmlinux /var/crash/201610291718/dump.201610291718
crash 7.1.4
Copyright(C)2002-2015 RedHat,Inc.
Copyright(C)2004,2005,2006,2010 IBM Corporation
Copyright(C)1999-2006 Hewlett-PackardCo
Copyright(C)2005,2006,2011,2012 FujitsuLimited
Copyright(C)2006,2007 VA LinuxSystemsJapan K.K.
Copyright(C)2005,2011 NEC Corporation
Copyright(C)1999,2002,2007 SiliconGraphics,Inc.
Copyright(C)1999,2000,2001,2002 MissionCriticalLinux,Inc.
This program is free software, covered by the GNU GeneralPublicLicense,
and you are welcome to change it and/or distribute copies of it under
certain conditions. Enter"help copying" to see the conditions.
This program has absolutely no warranty. Enter"help warranty"for details.
GNU gdb (GDB)7.6
Copyright(C)2013FreeSoftwareFoundation,Inc.
LicenseGPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type"show copying"
and "show warranty"for details.
This GDB was configured as "x86_64-unknown-linux-gnu"...
KERNEL: doc/ubuntu-compile/vmlinux
DUMPFILE:/var/crash/201610291718/dump.201610291718 [PARTIAL DUMP]
CPUS:4
DATE:SatOct2917:17:442016
UPTIME:00:03:39
LOAD AVERAGE:0.69,1.06,0.50
TASKS:582
NODENAME:Inspiron
RELEASE:4.4.13+
VERSION:#35 SMP Fri Oct 28 23:13:30 CST 2016
MACHINE: x86_64 (2526Mhz)
MEMORY:3.9 GB
PANIC:"sysrq: SysRq : Trigger a crash"
PID:2656
COMMAND:"bash"
TASK: ffff880081543e80 [THREAD_INFO: ffff880124db8000]
CPU:0
STATE: TASK_RUNNING (SYSRQ)
crash> bt
PID:2656 TASK: ffff880081543e80 CPU:0 COMMAND:"bash"
#0 [ffff880124dbbaf0] machine_kexec at ffffffff8105ae6b
#1 [ffff880124dbbb50] crash_kexec at ffffffff8110cb12
#2 [ffff880124dbbc20] oops_end at ffffffff81030c29
#3 [ffff880124dbbc48] no_context at ffffffff81069c35
#4 [ffff880124dbbca8] __bad_area_nosemaphore at ffffffff81069f00
#5 [ffff880124dbbcf0] bad_area at ffffffff8106a0d3
#6 [ffff880124dbbd18] __do_page_fault at ffffffff8106a5eb
#7 [ffff880124dbbd70] do_page_fault at ffffffff8106a6b2
#8 [ffff880124dbbd90] page_fault at ffffffff81832178
[exception RIP: sysrq_handle_crash+22]
RIP: ffffffff814f42b6 RSP: ffff880124dbbe48 RFLAGS:00010282
RAX:000000000000000f RBX:0000000000000063 RCX:0000000000000000
RDX:0000000000000000 RSI: ffff880137c0dc78 RDI:0000000000000063
RBP: ffff880124dbbe48 R8:0000000000000002 R9:00000000000003ed
R10:0000000000000001 R11:00000000000003ed R12:0000000000000004
R13:0000000000000000 R14: ffffffff81ebada0 R15:0000000000000000
ORIG_RAX: ffffffffffffffff CS:0010 SS:0018
#9 [ffff880124dbbe50] __handle_sysrq at ffffffff814f4a8a
#10 [ffff880124dbbe80] write_sysrq_trigger at ffffffff814f4f0f
#11 [ffff880124dbbe98] proc_reg_write at ffffffff81279782
#12 [ffff880124dbbeb8] __vfs_write at ffffffff8120b438
#13 [ffff880124dbbec8] vfs_write at ffffffff8120bdc9
#14 [ffff880124dbbf08] sys_write at ffffffff8120ca85
#15 [ffff880124dbbf50] entry_SYSCALL_64_fastpath at ffffffff8182fff2
RIP:00007fe506368a10 RSP:00007ffd28c06838 RFLAGS:00000246
RAX: ffffffffffffffda RBX:00000000006f4378 RCX:00007fe506368a10
RDX:0000000000000002 RSI:00000000011bc408 RDI:0000000000000001
RBP:00007ffd28c06770 R8:00007fe506637780 R9:00007fe506c6b700
R10:0000000000000001 R11:0000000000000246 R12:00007fe506c6d5d0
R13:0000000000000000 R14:00007fe506c8f168 R15:00007ffd28c06798
ORIG_RAX:0000000000000001 CS:0033 SS:002b
后記:
實際上編譯debug info后遇到兩個問題,第一個是預留的crash內存不足的問題,另外一個是預留足夠內存后雖然kdump服務正常了,但是內核崩潰的時候仍然不能啟動kdump服務
對於第一個預留內存不足的問題,后來查看kdump-tools和kexec-tools的源碼,原來kdump-config show執行的時候,就是讀取的/sys/kernel/kexec_crash_loaded這個文件的值,如果kexec_crash_loaded為0就表示kdump沒有處於ready狀態。接着查看內核源碼,/sys/kernel/kexec_crash_loaded文件對應內核變量kexec_crash_image,而這個變量只會在兩個系統調用中進行修改,一個是kexec_load另外一個是kexec_file_load,而我並沒有修改kexec相關的代碼,因此內核這塊出問題的概率比較小。
通過跟蹤kdump服務的啟動腳本執行過程,原來啟動kdump服務最終執行的命令是/bin/systemctl --no-pager start kdump-tools.service ,而systemctl則會通過/run/systemd/private這個socket與init進程通信,init最終又會執行kexec-tools中的kexec程序,在kexec執行的時候則會查找預留的carsh memory,當預留的內存不足的時候就會輸出"Could not find a free area of memory of xxxxx"錯誤信息,當預留的內存充足的時候,則會執行kexec_load系統調用進行加載。
對於第二個,kdump服務啟動后還不能正常使用kdump的問題,打開debug info和debug info對比,發現預留的crash memory位置不同,估計多半和內核的內存機制與kexec機制有關系,這塊不太懂了,沒有深入研究了。好在單獨剝離debug info后可以正常使用kdump。
grub啟動文件中crashkernel參數的解析,可以參考內核代碼parse_crashkernel
命令備記:
objcopy --only-keep-debug ./vmlinux.o vmlinux.debug
objcopy --strip-debug ./vmlinux.o
INSTALL_MOD_STRIP=1
strace -f -F -ff -o kdump /bin/systemctl --no-pager start kdump-tools.service
linux/boot/vmlinuz-4.4.13 root=UUID=1ba5f5c5-70c3-4936-b757-821899fe6264 ro quiet splash crashkernel=384M-:128M $vt_handoff