`
dato0123
  • 浏览: 936139 次
文章分类
社区版块
存档分类
最新评论

kdb代码分析(六)

 
阅读更多

我们带着这个参数回到kdb()里面去看,我们会发现,cpu都会跳到kdba_main_loop().这个函数定义于arch/i386/kdb/kdbasupport.c

577 /*

578 * kdba_main_loop

579 *

580 * Do any architecture specific set up before entering the main kdb loop.

581 * The primary function of this routine is to make all processes look the

582 * same to kdb, kdb must be able to list a process without worrying if the

583 * process is running or blocked, so make all process look as though they

584 * are blocked.

585 *

586 * Inputs:

587 * reason The reason KDB was invoked

588 * error The hardware-defined error code

589 * error2 kdb's current reason code. Initially error but can change

590 * acording to kdb state.

591 * db_result Result from break or debug point.

592 * regs The exception frame at time of fault/breakpoint. If reason

593 * is SILENT or CPU_UP then regs is NULL, otherwise it should

594 * always be valid.

595 * Returns:

596 * 0 KDB was invoked for an event which it wasn't responsible

597 * 1 KDB handled the event for which it was invoked.

598 * Outputs:

599 * Sets eip and esp in current->thread.

600 * Locking:

601 * None.

602 * Remarks:

603 * none.

604 */

605

606 int

607 kdba_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,

608 kdb_dbtrap_t db_result, struct pt_regs *regs)

609 {

610 int ret;

611 kdb_save_running(regs);

612 ret = kdb_main_loop(reason, reason2, error, db_result, regs);

613 kdb_unsave_running(regs);

614 return ret;

615 }

这个函数的核心部分自然是kdb_main_loop(),不过在它之前在它之后的这两个函数也有理由引起我们的注意.定义于kdb/kdbsupport.c:

782 /*

783 * kdb_save_running

784 *

785 * Save the state of a running process. This is invoked on the current

786 * process on each cpu (assuming the cpu is responding).

787 * Inputs:

788 * regs struct pt_regs for the process

789 * Outputs:

790 * Updates kdb_running_process[] for this cpu.

791 * Returns:

792 * none.

793 * Locking:

794 * none.

795 */

796

797 void

798 kdb_save_running(struct pt_regs *regs)

799 {

800 struct kdb_running_process *krp = kdb_running_process + smp_processor_id();

801 krp->p = current;

802 krp->regs = regs;

803 krp->seqno = kdb_seqno;

804 krp->irq_depth = hardirq_count() >> HARDIRQ_SHIFT;

805 kdba_save_running(&(krp->arch), regs);

806 }

807

808 /*

809 * kdb_unsave_running

810 *

811 * Reverse the effect of kdb_save_running.

812 * Inputs:

813 * regs struct pt_regs for the process

814 * Outputs:

815 * Updates kdb_running_process[] for this cpu.

816 * Returns:

817 * none.

818 * Locking:

819 * none.

820 */

821

822 void

823 kdb_unsave_running(struct pt_regs *regs)

824 {

825 struct kdb_running_process *krp = kdb_running_process + smp_processor_id();

826 kdba_unsave_running(&(krp->arch), regs);

827 krp->seqno = 0;

828 }

有这么一个结构体以及相应的数组,结构体定义于include/linux/kdbprivate.h:

428 /* Save data about running processes */

429

430 struct kdb_running_process {

431 struct task_struct *p;

432 struct pt_regs *regs;

433 int seqno; /* kdb sequence number */

434 int irq_depth; /* irq count */

435 struct kdba_running_process arch; /* arch dependent save data */

436 };

这其中struct kdba_running_process则定义于include/asm-i386/kdbprivate.h:

159 /* Arch specific data saved for running processes */

160

161 struct kdba_running_process {

162 long esp; /* CONFIG_4KSTACKS may be on a different stack */

163 };

熟悉x86体系结构的同志们一定不会对esp陌生.传说中的栈指针嘛.

kdb_save_runningkdb_unsave_running内部调用了一对函数,它们都来自include/asm-i386/kdbprivate.h:

165 static inline

166 void kdba_save_running(struct kdba_running_process *k, struct pt_regs *regs)

167 {

168 k->esp = current_stack_pointer;

169 }

170

171 static inline

172 void kdba_unsave_running(struct kdba_running_process *k, struct pt_regs *regs)

173 {

174 }

进一步跟踪你会发现,current_stack_pointer其实就是esp寄存器,不信你来看include/asm-i386/thread_info.h:

87 /* how to get the current stack pointer from C */

88 register unsigned long current_stack_pointer asm("esp") __attribute_used__;

标准的gcc内联汇编,相比kernel中众多的内联汇编语句,这句算是最好理解的了.

那么到这里基本上我们就知道了,kdb_save_runningkdb_unsave_running的作用无非就是在真正进入kdb之前保存之前那个进程的一些基本信息以及在从kdb出来以后及时的恢复之.

最后需要提醒一下的是,kdb_running_process不仅仅是结构体的名字,它还是一个数组的名字,该数组定义于kdb/kdbsupport.c:

780 struct kdb_running_process kdb_running_process[NR_CPUS];

对于smp来说,有几个处理器这个数组就有几个元素,对于up来说,自然就是一个成员.kdb_save_runningkdb_unsave_running中都有用到这个数组名,以它为起始地址去计算与某个CPU相关的那个struct kdb_running_process结构体变量,并让krp指向它.

这时候我们就可以全力关注kdb_main_loop().用下半身想想也知道这个函数必然定义于kdb/kdbmain.c:

1506 /*

1507 * kdb_main_loop

1508 *

1509 * The main kdb loop. After initial setup and assignment of the controlling

1510 * cpu, all cpus are in this loop. One cpu is in control and will issue the kdb

1511 * prompt, the others will spin until 'go' or cpu switch.

1512 *

1513 * To get a consistent view of the kernel stacks for all processes, this routine

1514 * is invoked from the main kdb code via an architecture specific routine.

1515 * kdba_main_loop is responsible for making the kernel stacks consistent for all

1516 * processes, there should be no difference between a blocked process and a

1517 * running process as far as kdb is concerned.

1518 *

1519 * Inputs:

1520 * reason The reason KDB was invoked

1521 * error The hardware-defined error code

1522 * reason2 kdb's current reason code. Initially error but can change

1523 * acording to kdb state.

1524 * db_result Result code from break or debug point.

1525 * regs The exception frame at time of fault/breakpoint. If reason

1526 * is SILENT or CPU_UP then regs is NULL, otherwise it

1527 * should always be valid.

1528 * Returns:

1529 * 0 KDB was invoked for an event which it wasn't responsible

1530 * 1 KDB handled the event for which it was invoked.

1531 * Locking:

1532 * none

1533 * Remarks:

1534 * none

1535 */

1536

1537 int

1538 kdb_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,

1539 kdb_dbtrap_t db_result, struct pt_regs *regs)

1540 {

1541 int result = 1;

1542 /* Stay in kdb() until 'go', 'ss[b]' or an error */

1543 while (1) {

1544 /*

1545 * All processors except the one that is in control

1546 * will spin here.

1547 */

1548 KDB_DEBUG_STATE("kdb_main_loop 1", reason);

1549 while (KDB_STATE(HOLD_CPU)) {

1550 /* state KDB is turned off by kdb_cpu to see if the

1551 * other cpus are still live, each cpu in this loop

1552 * turns it back on.

1553 */

1554 if (!KDB_STATE(KDB)) {

1555 KDB_STATE_SET(KDB);

1556 }

1557 }

1558 KDB_STATE_CLEAR(SUPPRESS);

1559 KDB_DEBUG_STATE("kdb_main_loop 2", reason);

1560 if (KDB_STATE(LEAVING))

1561 break; /* Another cpu said 'go' */

1562

1563 if (!kdb_quiet(reason))

1564 kdb_wait_for_cpus();

1565 /* Still using kdb, this processor is in control */

1566 result = kdb_local(reason2, error, regs, db_result);

1567 KDB_DEBUG_STATE("kdb_main_loop 3", result);

1568

1569 if (result == KDB_CMD_CPU) {

1570 /* Cpu switch, hold the current cpu, release the target one. */

1571 reason2 = KDB_REASON_SWITCH;

1572 KDB_STATE_SET(HOLD_CPU);

1573 KDB_STATE_CLEAR_CPU(HOLD_CPU, kdb_new_cpu);

1574 continue;

1575 }

1576

1577 if (result == KDB_CMD_SS) {

1578 KDB_STATE_SET(DOING_SS);

1579 break;

1580 }

1581

1582 if (result == KDB_CMD_SSB) {

1583 KDB_STATE_SET(DOING_SS);

1584 KDB_STATE_SET(DOING_SSB);

1585 break;

1586 }

1587

1588 if (result && result != 1 && result != KDB_CMD_GO)

1589 kdb_printf("/nUnexpected kdb_local return code %d/n", result);

1590

1591 KDB_DEBUG_STATE("kdb_main_loop 4", reason);

1592 break;

1593 }

1594 if (KDB_STATE(DOING_SS))

1595 KDB_STATE_CLEAR(SSBPT);

1596 return result;

1597 }

记住,此时此刻,所有的处理器都在这个函数中,只不过其中一个的reason是我们最早传递的那个KDB_REASON_KEYBOARD,而其余的几个cpureasonIPI引起的KDB_REASON_SWITCH,前者只有一个,但是地位相当于正室,后者可以有多个,但是地位相当于小妾.(注释中说,第一个那个叫做in control,而其它的就是不停的spin)

扫一下这个函数发现主要就是一个while(1)死循环.当然,其中有多个break可以跳出循环.不过有意思的是这个死循环内部还有另一个死循环,1549,while(KDB_STATE(HOLD_CPU)),这个就得回忆一下如风的往事了,回过去看kdb(),我们发现,在调用smp_kdb_stop()之前有一俄for循环,把每一个活着的cpu都给设置了两个flag,HOLD_CPUWAIT_IPI.(当然,in control的这个cpu没有设置)直到后来结束了kdba_main_loop()之后,才把这两个flag给人Clear.所以15491557这段while循环对于那些cpu来说,就相当于太上老君把孙猴子困在了炼丹炉中,非得等到一定时间以后才能放出来.这就是注释里说的spin.因此,在下面的代码其它的cpu暂时就不会执行了,只有那个in controlcpu会继续往下走,于是,从此以后,我们就先只关注这一个cpu,而其它的cpu,暂时可以忽略,你愿意想起她就想起她,像想起春天的一个梦,你愿意忘记她就忘记她,像忘记天边的一颗星.

1564,kdb_wait_for_cpus().这个函数就是等待大家都进入kdb.它这个函数的技巧就是判断大家的seqno是不是和kdb_seqno这个全局变量相等,因为实际上如果大家都执行了kdb()函数,那么我们前面说过,kdb_save_running()中就会把各cpu对应的那个seqno赋值为kdb_seqno.于是就应该有1477行的online等于kdb_data从而跳出for循环.反之如果某个cpu或者某几个cpu还没有执行过kdb()函数,那么它们的seqno就不会和全局的这个seqno相等,或者直接说就是初始值0.于是kdb_data就会和online不相等,从而会执行1479行开始的代码,并且开始下一轮的for循环,当然也没什么别的噱头,无非就是做些延时而已.最后只要大家都进入了kdb,这个函数就可以结束了.

分享到:
评论

相关推荐

    kdb-master.zip

    当我们提到“kdb-master.zip”时,这通常意味着我们正在讨论kdb+的一个源代码版本或者开发分支。本文将深入剖析kdb+的基本概念、核心特性以及在解压后的“kdb-master”目录中的关键文件和它们的功能。 1. **kdb+...

    linux下调试工具kdb

    4. **跟踪点**(tracepoints): kdb可以利用内建的跟踪点功能,记录内核运行中的特定事件,这对于性能分析和问题定位很有帮助。 5. **条件断点**: 可以设置基于特定条件的断点,只有当条件满足时才会触发。 6. **数据...

    q_and_kdb+.pdf

    ### Q_and_kdb+: 金融量化编程语言 ...通过以上分析可以看出,Q 和 kdb+ 为金融行业提供了一套完整的解决方案,不仅能够处理大规模数据集,还支持复杂的数据查询和实时分析。这对于金融市场中的高效决策具有重要意义。

    matlab方差分析代码-kdb.q.kalman.filter.beta.ETFs:kdb+/qkalmanbetamatlabpython

    matlab方差分析代码该项目的代码使用matlab,python和q / KDB +代码编写。 代码互为镜像 我的贡献是将matlab文件转换为q / KDB +,用于卡尔曼增益部分。 代码引用以下方程式:书:Ernest P Chan“算法交易-策略及其...

    kdb内核调试文档等

    - **内存分析**:KDB提供了强大的内存检查功能,如查找特定内存区域,分析内存泄漏等。 - **系统调用追踪**:可以跟踪系统调用,观察其参数和返回值,以了解内核与用户空间的交互。 - **内核环缓冲区查看**:KDB...

    linux源代码分析.zip

    Linux源代码分析是一个深入理解操作系统内核工作原理的重要实践,对于任何希望在系统级编程、设备驱动开发或者想要提升对操作系统理解的IT专业人员来说,这都是一个宝贵的资源。在这个"linux源代码分析.zip"文件中,...

    Linux操作系统内核分析+深入分析linux内核源代码-陈莉君.zip

    其次,"深入分析Linux-内核源代码-陈莉君-人民邮电出版社.pdf"可能侧重于通过源代码分析来理解内核的工作方式。源代码分析可以涵盖: 1. 内核模块:了解如何编写和加载内核模块,以扩展内核功能。 2. 调试技术:...

    linux内核代码分析

    在深入探讨"Linux内核代码分析"这一主题之前,我们首先要理解Linux内核的重要性。Linux内核是操作系统的核心部分,负责管理硬件资源、提供系统调用接口以及协调各个进程之间的交互。它是一套开放源码的软件,允许全...

    kdb_debugger.rar_V2

    通过阅读和分析这个源代码,我们可以了解到以下关键知识点: 1. **KGDB初始化**:KGDB的启动通常在内核启动过程中完成,`kdb_debugger.c`中的相关函数会设置调试器的通信通道,如串口或网络,并初始化必要的数据...

    Linux内核源代码分析.pdf

    《Linux内核源代码分析》是一本深入探讨Linux操作系统核心机制的专业书籍。它不仅涵盖了Linux内核的基础架构,还详细解析了其工作原理,旨在帮助读者深入理解这一开源操作系统的精髓。通过阅读这本书,读者可以了解...

    Linux内核源代码情景分析(上)(下)

    《Linux内核源代码情景分析》是一套深入探讨Linux内核源码的书籍,分为上下两部分。本书旨在帮助读者理解Linux操作系统的核心运作机制,通过分析源代码来揭示其内部的工作原理。书中不仅涵盖了基本的内核架构,还...

    商业编程-源码-KDB论坛 v1.2.0.zip

    源码分析可以帮助我们了解如何在实际项目中高效地利用KDB进行数据存储和查询,以及如何构建适应高并发场景的应用。 其次,作为一个社区平台,KDB论坛 v1.2.0的源码涵盖了用户管理、话题发布、评论互动、搜索功能等...

    Linux内核2·4版源代码分析大全

    《Linux内核2.4版源代码分析大全》是一本深度剖析Linux内核的专业书籍,旨在帮助读者理解和掌握Linux内核的工作原理。该书详细解析了2.4版本的内核源代码,这一版本在Linux发展史上具有重要的里程碑意义,为后来的...

    kdb_debugger.rar_interface

    标题中的“kdb_debugger.rar_interface”暗示了我们要讨论的是一个与调试相关的接口,特别是针对KDB...通过分析“kdb_debugger.c”,我们可以学习如何构建这样的跨系统调试接口,并从中获取调试高级功能的实现思路。

    LINUX内核源代码情景分析

    《LINUX内核源代码情景分析》这本书是深入理解Linux操作系统内核的重要参考资料。它以情境分析的方式,带领读者逐步探索Linux内核的工作原理和设计思路。以下将围绕该书内容,详细介绍Linux内核源代码的相关知识点。...

    kxsystems.github.io:GitHub上的kdb +和q存储库索引

    kdb+和q是金融行业中广泛使用的高性能数据库和编程语言,尤其在实时数据处理和时序数据分析方面表现出色。kxsystems.github.io是kdb+社区在GitHub上的一个项目,它提供了一个综合的索引来展示用户创建的kdb+和q相关...

    qprofiler:kdb+q 的简单分析器

    **qProfiler:kdb+/q的简易分析器** 在kdb+/q编程环境中,性能优化是至关重要的,因为高效的数据处理能力是这个低延迟、内存数据库系统的核心优势。`qProfiler`工具就是为了帮助开发者深入了解代码执行性能而设计的...

    linux早期内核代码分析

    《Linux早期内核代码分析》这本书是针对Linux操作系统内核早期版本进行深入解析的宝贵资料。在阅读和学习这本书的过程中,你可以了解到Linux内核的基本架构、设计原理以及关键功能的实现细节。以下是一些主要的知识...

Global site tag (gtag.js) - Google Analytics