先来看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(),你说这不瞎耽误工夫么?你直接调用不就行了么?有这工夫写这段无聊的汇编代码还不如好好品味品味色戒里汤唯姐姐精彩绝伦的床戏呢.

Logo

更多推荐