留着以后看,呵呵
多线程程序中, 经常遇到线程死锁的问题。 出现死锁的状况,很多时候像盲人摸象般的加调试信息,看程序“已经跑在哪里”了。 但同时,也需要这个死锁能经常不断的出现,才能找到问题所在。 利用调试器提供的便利,我们可以找到更好地解决办法。 下面的过程中,逐鹿使用的是一个AXD调试器,对象程序是ARM的eCos程序, 其中几个线程不见动静(已经死锁)。 于是选择其中一个线程,定位该线程死锁的位置。 1. 找到该线程的stack位置 对照程序源代码,不难发现线程的thread handle变量名,在调试器的symbol窗口中查看变量的地址。 暂停程序运行,在memory窗口中,定位到该变量地址处,这个地址处保留有一个线程控制块结构, 类型为Cyg_HardwareThread。 class Cyg_HardwareThread { CYG_ADDRESS stack_base; // pointer to base of stack area cyg_uint32 stack_size; // size of stack area in bytes CYG_ADDRESS stack_limit; // movable stack limit CYG_ADDRESS stack_ptr; // pointer to saved state on stack cyg_thread_entry *entry_point; // main entry point (code pointer!) CYG_ADDRWORD entry_data; // entry point argument .... }; 从该结构看出,thread handle指向的地址, 加上偏移3 int (24 byte)的地方, 是一个 stack_ptr, 这个stack_ptr即是进程当前的栈顶指针. 2. 找到线程阻塞之前的sp, lr, pc寄存器. 在此利用AXD的查看memory窗口, 定位到stack_ptr的值指向的地址. 这个地址处, 实际上保存着 r0 - r12, sp, lr, pc 一共16个寄存器的内容. 因此sp, lr, pc 分别在 stack_prt指向的地址偏移 13 int, 14 int, 15 int处. sp *( (int*)stack_ptr + 13 ) lr *( (int*)stack_ptr + 14 ) pc *( (int*)stack_ptr + 15 ) 3. 察看线程阻塞之前的函数调用现场 有了sp, lr, pc, 接下来的事情就容易了. 查看当前寄存器窗口, 先记录下当前的 sp(r13), lr(r14) 和 pc的值, 将第2步找到的死锁线程的sp, lr, pc值填进去。 然后,打开BackTrace窗口。不出所料,线程的函数调用栈一目了然, 从哪里调进来,走到哪步不动,全部清清楚楚。 至此,我们圆满完成调试。 (如果还需要继续运行程序调试,继续之前别忘了将旧的sp,lr和pc重填回去,呵呵)
原帖地址:http://blogold.chinaunix.net/u3/96727/showart_2038896.html
文章评论(0条评论)
登录后参与讨论