先来看KDB_ENTER().这是与体系结构相关的宏.对于i386来说,我们得看i386特定的patch(即kdb-v4.4-2.6.22-i386-1):
14434 Index: linux/include/asm-i386/kdb.h
14435 ===================================================================
14436 --- /dev/null
14437 +++ linux/include/asm-i386/kdb.h
14438 @@ -0,0 +1,45 @@
14439 +#ifndef _ASM_KDB_H
14440 +#define _ASM_KDB_H
14441 +
14442 +/*
14443 + * Kernel Debugger Architecture Dependent Global Headers
14444 + *
14445 + * This file is subject to the terms and conditions of the GNU General Public
14446 + * License. See the file "COPYING" in the main directory of this archive
14447 + * for more details.
14448 + *
14449 + * Copyright (c) 1999-2004 Silicon Graphics, Inc. All Rights Reserved.
14450 + */
14451 +
14452 +/*
14453 + * KDB_ENTER() is a macro which causes entry into the kernel
14454 + * debugger from any point in the kernel code stream. If it
14455 + * is intended to be used from interrupt level, it must use
14456 + * a non-maskable entry method.
14457 + */
14458 +#define KDB_ENTER() do {if (kdb_on && !KDB_IS_RUNNING()) { asm("/tint $129/n"); }} while(0)
14459 +
这里的KDB_IS_RUNNING()虽然意思很明了,我们还是看一下它的定义:
4273 +/*
4274 + * kdb_initial_cpu is initialized to -1, and is set to the cpu
4275 + * number whenever the kernel debugger is entered.
4276 + */
4277 +extern volatile int kdb_initial_cpu;
4278 +extern atomic_t kdb_event;
4279 +extern atomic_t kdb_8250;
4280 +#ifdef CONFIG_KDB
4281 +#define KDB_IS_RUNNING() (kdb_initial_cpu != -1)
4282 +#define KDB_8250() (atomic_read(&kdb_8250) != 0)
4283 +#else
4284 +#define KDB_IS_RUNNING() (0)
4285 +#define KDB_8250() (0)
4286 +#endif /* CONFIG_KDB */
很明显只要kdb_initial_cpu不为-1就表示KDB_IS_RUNNING,或者说只要我们进入了kdb,kdb_initial_cpu肯定不会是-1,而是表示cpu的编号.
asm表示里面包含的是汇编指令.那么这里着int $129是什么意思呢?int是中断指令,这里的中断号是129,而129换成十六进制就是0x81.与此同时我们发现i386的那个patch中有下面一段:
14700 Index: linux/include/asm-i386/mach-default/irq_vectors.h
14701 ===================================================================
14702 --- linux.orig/include/asm-i386/mach-default/irq_vectors.h
14703 +++ linux/include/asm-i386/mach-default/irq_vectors.h
14704 @@ -29,6 +29,7 @@
14705 #define FIRST_EXTERNAL_VECTOR 0x20
14706
14707 #define SYSCALL_VECTOR 0x80
14708 +#define KDBENTER_VECTOR 0x81
14709
14710 /*
14711 * Vectors 0x20-0x2f are used for ISA interrupts.
14712 @@ -48,6 +49,7 @@
14713 #define INVALIDATE_TLB_VECTOR 0xfd
14714 #define RESCHEDULE_VECTOR 0xfc
14715 #define CALL_FUNCTION_VECTOR 0xfb
14716 +#define KDB_VECTOR 0xf9
14717
14718 #define THERMAL_APIC_VECTOR 0xf0
14719 /*
这里我们看到KDBENTER_VECTOR被定义成0x81.你凭良心说,KDBENTER_VECTOR你是不是见过?你要说没见过那你一定是瞎说,你说假话的水平和新闻联播有得一拼.当初在初始化那部分,不是有一个kdba_arch_init()么?再来回顾一下:
8592 +static int __init
8593 +kdba_arch_init(void)
8594 +{
8595 +#ifdef CONFIG_SMP
8596 + set_intr_gate(KDB_VECTOR, kdb_interrupt);
8597 +#endif
8598 + set_intr_gate(KDBENTER_VECTOR, kdb_call);
8599 + return 0;
8600 +}
没错,就是这里,设置了一个中断门.至于什么是中断门这不用我多说了吧,总之这里这行的效果就是使得中断向量KDBENTER_VECTOR和中断服务函数kdb_call给联系了起来.而kdb_call也是跟体系结构相关的,对于i386来说:
8920 Index: linux/arch/i386/kernel/entry.S
8921 ===================================================================
8922 --- linux.orig/arch/i386/kernel/entry.S
8923 +++ linux/arch/i386/kernel/entry.S
8924 @@ -978,6 +978,26 @@ ENTRY(alignment_check)
8925 CFI_ENDPROC
8926 END(alignment_check)
8927
8928 +#ifdef CONFIG_KDB
8929 +
8930 +ENTRY(kdb_call)
8931 + RING0_INT_FRAME
8932 + pushl %eax # save orig EAX
8933 + CFI_ADJUST_CFA_OFFSET 4
8934 + SAVE_ALL
8935 + movl %esp,%ecx # struct pt_regs
8936 + movl $0,%edx # error_code
8937 + movl $1,%eax # KDB_REASON_ENTER
8938 + call kdb
8939 + jmp restore_all
8940 + CFI_ENDPROC
8941 +
8942 +#ifdef CONFIG_SMP
8943 +BUILD_INTERRUPT(kdb_interrupt,KDB_VECTOR)
8944 +#endif /* CONFIG_SMP */
8945 +
8946 +#endif /* CONFIG_KDB */
8947 +
8948 ENTRY(divide_error)
8949 RING0_INT_FRAME
8950 pushl $0 # no error code
哦,哦,这里可是一段汇编代码.不是每个人都能看懂的.不过我们也不用每行都看懂,其实很明显的有一行,即8938行,”call kdb”,这是干嘛?地球人都知道,调用函数kdb().这时候我们猛然发现,原来KDB_ENTER()绕来绕去,最终还是要调用kdb(),你说这不瞎耽误工夫么?你直接调用不就行了么?有这工夫写这段无聊的汇编代码还不如好好品味品味色戒里汤唯姐姐精彩绝伦的床戏呢.