这是一个很冷门的话题,它受关注的程度永远也比不上陈冠希老师的摄影作品.不过人在江湖身不由己,因为工作原因我不得不接触它,不得不了解一点kdb的代码.
Kdb,也叫kernel debugger.是Linux系统的内核调试器,它是一个开源工具,乃是SGI公司开发的.kdb适用于调试内核空间的程序代码,譬如进行设备驱动程序调试,内核模块的调试.Official的Linux kernel并不包含kdb,所以我们必须从sgi的网站上去下载kdb.关于如何安装如何使用kdb,并非本系列文章的重点.实际上,关于kdb的入门,关于kdb的应用,许多年前,当我还在复旦念书的时候,当我才刚学会几个简单的Unix命令的时候,我就注意到网络上有人发表过这类文章了,所以介绍kdb,推广kdb,并不是我写此文的目的.我所写的是针对kdb本身的分析,针对的是kdb的源代码,或者说kdb的实现.
Linux内核每隔一段时间就会发布一个最新的版本,而kdb则会相应的发布与之匹配的补丁.比如你Linux发布了2.6.10的kernel,那么我sgi这边就发布针对2.6.10的kernel的补丁.你发布了2.6.20的kernel,我就发布针对你2.6.20的补丁.比如我之前为了看2.6.22.1的kernel,我就下载了针对2.6.22.1的补丁,或者叫做patch.一共有三个patch:
localhost:/usr/src # ls kdb-v4.4-2.6.22-*
kdb-v4.4-2.6.22-common-1 kdb-v4.4-2.6.22-i386-1 kdb-v4.4-2.6.22-x86_64-1
这三个patch有多长呢:
localhost:/usr/src # wc -l kdb-v4.4-2.6.22-*
17943 kdb-v4.4-2.6.22-common-1
14753 kdb-v4.4-2.6.22-i386-1
14249 kdb-v4.4-2.6.22-x86_64-1
46945 total
我的神,46945行.
第一个patch是最基本的patch.
第二个patch是针对i386的.
第三个patch是针对x86_64的.
如果你只对i386感兴趣,那么只关注前两个patch就可以了.
首先我们就来看一下这个common的patch.这个patch开门见山的介绍了它对内核中哪些文件进行了修改,或者增加了哪些文件.
---
Documentation/kdb/kdb.mm | 492 +++++
Documentation/kdb/kdb_bp.man | 197 ++
Documentation/kdb/kdb_bt.man | 228 ++
Documentation/kdb/kdb_env.man | 46
Documentation/kdb/kdb_ll.man | 134 +
Documentation/kdb/kdb_md.man | 136 +
Documentation/kdb/kdb_ps.man | 96
Documentation/kdb/kdb_rd.man | 170 +
Documentation/kdb/kdb_sr.man | 68
Documentation/kdb/kdb_ss.man | 109 +
Documentation/kdb/slides | 1382 ++++++++++++++
Makefile | 1
drivers/char/keyboard.c | 10
drivers/hid/usbhid/hid-core.c | 20
drivers/hid/usbhid/usbkbd.c | 15
drivers/serial/8250.c | 53
drivers/serial/8250_early.c | 34
drivers/serial/sn_console.c | 73
drivers/usb/host/ohci-hcd.c | 47
drivers/usb/host/ohci-pci.c | 10
drivers/usb/host/ohci-q.c | 62
fs/proc/mmu.c | 16
fs/proc/proc_misc.c | 114 +
include/linux/console.h | 5
include/linux/dis-asm.h | 347 +++
include/linux/kdb.h | 166 +
include/linux/kdbprivate.h | 485 +++++
include/linux/sysctl.h | 1
init/main.c | 32
kdb/ChangeLog | 1672 +++++++++++++++++
kdb/Makefile | 28
kdb/kdb_bp.c | 619 ++++++
kdb/kdb_bt.c | 179 +
kdb/kdb_cmds | 32
kdb/kdb_id.c | 236 ++
kdb/kdb_io.c | 671 ++++++
kdb/kdbmain.c | 4034 ++++++++++++++++++++++++++++++++++++++++++
kdb/kdbsupport.c | 1134 +++++++++++
kdb/modules/Makefile | 14
kdb/modules/kdbm_pg.c | 645 ++++++
kdb/modules/kdbm_sched.c | 57
kdb/modules/kdbm_task.c | 199 ++
kdb/modules/kdbm_vm.c | 841 ++++++++
kdb/modules/kdbm_x86.c | 1096 +++++++++++
kdb/modules/kdbm_xpc.c | 1105 +++++++++++
kernel/exit.c | 3
kernel/kallsyms.c | 22
kernel/module.c | 19
kernel/printk.c | 14
kernel/sched.c | 79
kernel/signal.c | 49
mm/hugetlb.c | 19
mm/swapfile.c | 22
53 files changed, 17330 insertions(+), 8 deletions(-)
Kdb一个很突出的特点就是它牵涉的模块倍儿多.很明显,这其中有两个文件可能是我们故事的起点.一个是init/main.c,一个是kdb/kdbmain.c.
我们先看这个patch对init/main.c的修改.
4909 Index: linux/init/main.c
4910 ===================================================================
4911 --- linux.orig/init/main.c
4912 +++ linux/init/main.c
4913 @@ -66,6 +66,10 @@
4914 #include <asm/smp.h>
4915 #endif
4916
4917 +#ifdef CONFIG_KDB
4918 +#include <linux/kdb.h>
4919 +#endif /* CONFIG_KDB */
4920 +
4921 /*
4922 * This is one of the first .c files built. Error out early if we have compiler
4923 * trouble.
4924 @@ -187,6 +191,26 @@ static const char *panic_later, *panic_p
4925
4926 extern struct obs_kernel_param __setup_start[], __setup_end[];
4927
4928 +#ifdef CONFIG_KDB
4929 +static int __init kdb_setup(char *str)
4930 +{
4931 + if (strcmp(str, "on") == 0) {
4932 + kdb_on = 1;
4933 + } else if (strcmp(str, "on-nokey") == 0) {
4934 + kdb_on = 2;
4935 + } else if (strcmp(str, "off") == 0) {
4936 + kdb_on = 0;
4937 + } else if (strcmp(str, "early") == 0) {
4938 + kdb_on = 1;
4939 + kdb_flags |= KDB_FLAG_EARLYKDB;
4940 + } else
4941 + printk("kdb flag %s not recognised/n", str);
4942 + return 0;
4943 +}
4944 +
4945 +__setup("kdb=", kdb_setup);
4946 +#endif /* CONFIG_KDB */
4947 +
4948 static int __init obsolete_checksetup(char *line)
4949 {
4950 struct obs_kernel_param *p;
4951 @@ -606,6 +630,14 @@ asmlinkage void __init start_kernel(void
4952 pgtable_cache_init();
4953 prio_tree_init();
4954 anon_vma_init();
4955 +
4956 +#ifdef CONFIG_KDB
4957 + kdb_init();
4958 + if (KDB_FLAG(EARLYKDB)) {
4959 + KDB_ENTER();
4960 + }
4961 +#endif /* CONFIG_KDB */
4962 +
4963 #ifdef CONFIG_X86
4964 if (efi_enabled)
4965 efi_enter_virtual_mode();
很明显,增加了两个函数kdb_setup()和kdb_init().kdb_setup()的作用是让你在启动的时候可以传递一个类似于”kdb=on”或者”kdb=off”的内核参数,换言之,它相当于一个开关,给你提供了一种选择,在启动系统的时候你就可以选择打开kdb或者索性关掉kdb.如果你选择了kdb=off,那么就相当于艳照门事件之前陈冠希老师把他的硬盘格式化掉,后面所有的故事都不可能再发生了.