作为Linux内核关键的调试技术,可以修改内核定时器来定位系统僵死问题.doc

上传人:白大夫 文档编号:3377702 上传时间:2019-08-19 格式:DOC 页数:4 大小:25.50KB
返回 下载 相关 举报
作为Linux内核关键的调试技术,可以修改内核定时器来定位系统僵死问题.doc_第1页
第1页 / 共4页
亲,该文档总共4页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《作为Linux内核关键的调试技术,可以修改内核定时器来定位系统僵死问题.doc》由会员分享,可在线阅读,更多相关《作为Linux内核关键的调试技术,可以修改内核定时器来定位系统僵死问题.doc(4页珍藏版)》请在三一文库上搜索。

1、作为Linux内核关键的调试技术,可以修改内核定时器来定位系统僵死问题1.简介在内核调试中,会经常出现内核僵死的问题,也就是发生死循环,内核不能产生调度。导致内核失去响应。这种情况下我们可以采用修改系统内核中的系统时钟的中断来定位发生僵死的进程和函数名称。因为内核系统系统时钟采用的是硬件中断的形式存在,所以,软件发生僵死的时候,系统时钟照样会发生中断。1.1、我们在命令行输入:# cat /proc/interrupts# cat /proc/interrupts CPU0 30: 8316 s3c S3C2410 Timer Tick - 系统时钟 33: 0 s3c s3c-mci 34:

2、 0 s3c I2SSDI 35: 0 s3c I2SSDO 37: 12 s3c s3c-mci 42: 0 s3c ohci_hcd:usb1 43: 0 s3c s3c2440-i2c 51: 1047 s3c-ext eth0 60: 0 s3c-ext s3c-mci 70: 16 s3c-uart0 s3c2440-uart 71: 26 s3c-uart0 s3c2440-uart 79: 8 s3c-adc s3c2410_acTIon 80: 1732 s3c-adc s3c2410_acTIon 83: 0 - s3c2410-wdtErr: 0#30: 8316 s3c

3、S3C2410 TImer TIck 这个就是系统时钟,中断号为301.2、在内核代码中搜索S3C2410 Timer Tick字样。在Time.c (archarmplat-s3c24xx)文件中有如下代码。static struct irqaction s3c2410_timer_irq = .name = S3C2410 Timer Tick, .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, .handler = s3c2410_timer_interrupt,;/* * IRQ handler for the timer */st

4、atic irqreturn_ts3c2410_timer_interrupt(int irq, void *dev_id)#if 1 static pid_t pre_pid; static int cnt=0; /时钟中断的中断号是30 if(irq=30) if(pre_pid=current-pid) cnt+; else cnt=0; pre_pid=current-pid; /如果本进程十秒钟还没有离开的话,就会打印下面的语句 if(cnt=10*HZ) cnt=0; printk(s3c2410_timer_interrupt : pid = %d, task_name = %s

5、n,current-pid,current-comm); #endif write_seqlock( timer_tick(); write_sequnlock( return IRQ_HANDLED;、每个进程都有一个结构task_struct用来存储进程的一些状态信息。current是一个宏,表示当前进程的信息,也就是一个task_struct结构体,所以current-pid为当前进程的pid号,current-comm表示当前进程的name。、HZ也是一个宏定于,表示1s需要多少次中断。10*HZ表示就就是10s需要多少次中断!2、测试编译内核:#make uImage加载一个带有wh

6、ile(1);的驱动程序,系统发送僵死,系统会打印如下信息:# insmod first_drv.ko # ./firstdrvtest ons3c2410_timer_interrupt : pid = 770, task_name = firstdrvtests3c2410_timer_interrupt : pid = 770, task_name = firstdrvtest根据上述信息可知,发送僵死的进程号为:770,发送僵死的进程名称为:firstdrvtest3、继续完善,增加PC值,更加详细的定位僵死的地方我们知道,当中断发送的时候,在汇编中会调用asm_do_irq函数,.m

7、acro irq_handler get_irqnr_preamble r5, lr1: get_irqnr_and_base r0, r6, r5, lr movne r1, sp routine called with r0 = irq number, r1 = struct pt_regs * adrne lr, 1b bne asm_do_IRQ #调用C语言的函数asm_do_IRQ 函数原型:asmlinkage void _exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs) static pid_t pre_p

8、id; static int cnt=0; struct pt_regs *old_regs = set_irq_regs(regs); struct irq_desc *desc = irq_desc + irq; /* * Some hardware gives randomly wrong interrupts. Rather * than crashing, do something sensible. */ if (irq = NR_IRQS) desc = irq_enter(); desc_handle_irq(irq, desc); /* AT91 specific worka

9、round */ irq_finish(irq); irq_exit(); set_irq_regs(old_regs); asm_do_IRQ这个函数,在这个函数里面我们发现了一个结构体:struct pt_regs,这个结构体就用来保存发生中断时的现场,其中PC值就是:ARM_pc我们将上面在:s3c2410_timer_interrupt里面加入的信息都删除,并在:asm_do_IRQ函数里面加修改后改函数为:(红色为添加的程序)asmlinkage void _exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)#if

10、 1 static pid_t pre_pid; static int cnt=0; /时钟中断的中断号是30 if(irq=30) if(pre_pid=current-pid) cnt+; else cnt=0; pre_pid=current-pid; if(cnt=10*HZ) cnt=0; printk(s3c2410_timer_interrupt : pid = %d, task_name = %sn,current-pid,current-comm); printk(pc = %08xn,regs-ARM_pc);/打印pc值 #endif static pid_t pre_p

11、id; static int cnt=0; struct pt_regs *old_regs = set_irq_regs(regs); struct irq_desc *desc = irq_desc + irq; /* * Some hardware gives randomly wrong interrupts. Rather * than crashing, do something sensible. */ if (irq = NR_IRQS) desc = irq_enter(); desc_handle_irq(irq, desc); /* AT91 specific worka

12、round */ irq_finish(irq); irq_exit(); set_irq_regs(old_regs); 4、测试:# insmod first_drv.ko # ./firstdrvtest ons3c2410_timer_interrupt : pid = 771, task_name = firstdrvtestpc = bf0000844.1、查看内核中内核函数、加载的函数的地址#cat /proc/kallsyms /kallsyms.txt找到pc地址为bf000084附近的函数:.00000000 a first_drv.c first_drvbf000088

13、t first_drv_init first_drvbf000140 t first_drv_exit first_drvc48761cc ? _mod_license87 first_drvbf000940 b $d first_drvbf000740 d first_drv_fops first_drvbf000740 d $d first_drvbf00003c t first_drv_write first_drv#大概就在这个函数里面,可以确定僵死的地方在bf000000 t first_drv_open first_drvbf000000 t $a first_drvbf00003

14、8 t $d first_drvbf00003c t $a first_drvbf000114 t $d first_drvbf00094c b firstdrv_class first_drvbf000950 b firstdrv_class_dev first_drvbf000140 t $a first_drvbf000184 t $d first_drv00000000 a first_drv.mod.c first_drvc48761d8 ? _module_depends first_drvbf0008ac d $d first_drvc4876204 ? _mod_vermagi

15、c5 first_drvc01bd44c u class_device_create first_drvc008ca94 u register_chrdev first_drvc01bd668 u class_device_unregister first_drvbf000948 b major first_drvbf000944 b gpfcon first_drvc0031ad0 u _iounmap first_drvc01bc968 u class_create first_drvbf0007c0 d _this_module first_drvbf000088 t init_modu

16、le first_drvc008c9dc u unregister_chrdev first_drvbf000140 t cleanup_module first_drvc01bc9dc u class_destroy first_drvbf000940 b gpfdat first_drvc0031a6c u _arm_ioremap first_drvc0172f80 u _copy_from_user first_drvc01752e0 u _memzero first_drv4.2、查看反汇编#arm-linux-objdump -D first_drv.ko first_drv.di

17、s在kallsyms.txt中可以知道,first_drv_write的入口地址为bf00003c打开first_drv.dis,如何查找真正僵死的位置?(1)首先从反汇编文件中找到位置为00000000的函数:00000000 :(2)在kallsyms.txt中,first_drv_open 实际位置是:bf000000(3)根据上面的信息,可知知道,在反汇编中,发送僵死的位置为00000084 - 4 处(4)查找00000084处代码在函数:first_drv_write中0000003c : 3c: e1a0c00d mov ip, sp 40: e92dd800 stmdb sp!

18、, fp, ip, lr, pc 44: e24cb004 sub fp, ip, #4 ; 0x4 48: e24dd004 sub sp, sp, #4 ; 0x4 4c: e3cd3d7f bic r3, sp, #8128 ; 0x1fc0 50: e3c3303f bic r3, r3, #63 ; 0x3f 54: e5933008 ldr r3, r3, #8 58: e0910002 adds r0, r1, r2 5c: 30d00003 sbcccs r0, r0, r3 60: 33a03000 movcc r3, #0 ; 0x0 64: e3530000 cmp r3, #0 ; 0x0 68: e24b0010 sub r0, fp, #16 ; 0x10 6c: 1a00001c bne e4 0x5c 70: ebfffffe bl 70 0x34 74: ea00001f b f8 0x70 78: e3520000 cmp r2, #0 ; 0x0 7c: 11a01002 movne r1, r2 80: 1bfffffe blne 80 #错误在这,死循环! 84: ea00001f b 108注意:在arm中,中断保存的PC是当前指令加4,所以真正僵死的位置是:bf00000080,也就是:80

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1