免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: wiseker
打印 上一主题 下一主题

请问下有没有什么工具可以打印出linux内核的调用栈 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2008-08-21 15:05 |只看该作者
Linux的systemtap 就是仿dtrace做的,可以跟踪内核。

楼主的问题可以用systemtap解决:

1. 写好systemtap的脚本

2. 运行测试重现问题,查看systemtap的输出。


最理想的当然还是直接查看内核 ...


谢谢哈!我先学习学习这个软件!

论坛徽章:
0
12 [报告]
发表于 2008-08-22 13:14 |只看该作者
可以使用魔术键打印所有任务的调用栈(包括就绪队列的),不过对于正在运行的任务不能打印。

论坛徽章:
0
13 [报告]
发表于 2008-08-22 13:39 |只看该作者
原帖由 wuqixuan 于 2008-8-22 13:14 发表
可以使用魔术键打印所有任务的调用栈(包括就绪队列的),不过对于正在运行的任务不能打印。



嗯,接近于我想说的功能了,这个需要给Linux加patch实现吗,还是built-in的?有文档吗?

Solaris的kernel debug可以查看所有的任务的调用栈,sleep queue, run queue和on CPU的所有任务的调用栈。

对楼主的问题来说,不论是system hang还是进程的hang,内核的任务不在CPU上运行的可能性也是很大的,可以试试看。

论坛徽章:
0
14 [报告]
发表于 2008-08-22 14:25 |只看该作者
原帖由 Solaris12 于 2008-8-22 13:39 发表



嗯,接近于我想说的功能了,这个需要给Linux加patch实现吗,还是built-in的?有文档吗?

Solaris的kernel debug可以查看所有的任务的调用栈,sleep queue, run queue和on CPU的所有任务的调用栈。

...


in tree的, 存在了很多年了。

我的笔记:

113, sysrq

     1) 激活sysrq这个功能
        
                # echo -n 1 > /proc/sys/kernel/sysrq

        然后可以查看当前值, 用cat或者sysctl -a |grep sysrq都能看到。
        也可以在/etc/sysctl.conf中加一句:
               
                kernel.sysrq = 1
       
     2) 在console下
            
       
        按Alt-SysRq-<sysrq的功能键>就会执行sysrq的动作, 功能键有:

                reBoot
                Crashdump
                show-all-locks(D)
                tErm
                Full
                kIll
                saK
                showMem
                Nice
                powerOff
                showPc
                show-all-timers(Q)
                unRaw
                Sync
                showTasks
                Unmount
                shoW-blocked-tasks

        例如按Alt-SysRq-D则打印所有的锁信息。


        注意,除了PC-AT机器的键盘,没有有SysRq键的 这种情况下,还可以:
               
                # echo d > /proc/sysrq-trigger  //show-all-locks(D)
       
        控制loglevel为1 (范围是0~8,不要设置为8,那样too noisy)
               
                # echo 1 > /proc/sysrq-trigger

论坛徽章:
0
15 [报告]
发表于 2008-08-22 16:08 |只看该作者
           可以使用魔术键打印所有任务的调用栈(包括就绪队列的)


试了一把,这个功能很好用啊

/Documentation/sysrq.txt 有详细说明

谢谢!

论坛徽章:
0
16 [报告]
发表于 2008-08-22 23:11 |只看该作者
有一个办法可以把所有任务全部打印出来,就是自己写一个内核模块,然后在用户态通过某种方式(可以通过写虚拟设备等),执行内核模块的一个函数 ,这个函数就是调用 show_state,魔术键的sysrq.c就是调用这个函数打印所有任务的调用栈的,由于当前任务是自己的测试任务,因此其他任务可以全部打印(不过SMP的情况,其他CPU的正在执行的还是搞不定)。

当然自己也可以在内核模块内重新写这个函数,把最后的一个判断去掉。不过不清楚内核为什么要加这个判断,可能是怕调用栈不准确

static void show_task(task_t * p)
{
        task_t *relative;
        unsigned state;
        unsigned long free = 0;
        static const char *stat_nam[] = { "R", "S", "D", "T", "t", "Z", "X" };

        printk("%-13.13s ", p->comm);
        state = p->state ? __ffs(p->state) + 1 : 0;
        if (state < ARRAY_SIZE(stat_nam))
                printk(stat_nam[state]);
        else
                printk("?");
#if (BITS_PER_LONG == 32)
        if (state == TASK_RUNNING)
                printk(" running ");
        else
                printk(" %08lX ", thread_saved_pc(p));
#else
        if (state == TASK_RUNNING)
                printk("  running task   ");
        else
                printk(" %016lx ", thread_saved_pc(p));
#endif
#ifdef CONFIG_DEBUG_STACK_USAGE
        {
                unsigned long * n = (unsigned long *) (p->thread_info+1);
                while (!*n)
                        n++;
                free = (unsigned long) n - (unsigned long)(p->thread_info+1);
        }
#endif
        printk("%5lu %5d %6d ", free, p->pid, p->parent->pid);
        if ((relative = eldest_child(p)))
                printk("%5d ", relative->pid);
        else
                printk("      ");
        if ((relative = younger_sibling(p)))
                printk("%7d", relative->pid);
        else
                printk("       ");
        if ((relative = older_sibling(p)))
                printk(" %5d", relative->pid);
        else
                printk("      ");
        if (!p->mm)
                printk(" (L-TLB)\n");
        else
                printk(" (NOTLB)\n");

        if (state != TASK_RUNNING)               //  这里判断了,原来只要是就绪态的都不打印,还是比较恶心的。我前面的描述有误
                show_stack(p, NULL);
}

论坛徽章:
0
17 [报告]
发表于 2008-08-25 22:03 |只看该作者
有一个办法可以把所有任务全部打印出来,就是自己写一个内核模块,然后在用户态通过某种方式(可以通过写虚拟设备等),执行内核模块的一个函数,这个函数就是调用 show_state,魔术键的sysrq.c就是调用这个函数打印所有任务的调用栈的,由于当前任务是自己的测试任务,因此其他任务可以全部打印(不过 SMP的情况,其他CPU的正在执行的还是搞不定)。


嗯,确实这个功能可以扩展哈,我觉得这也算是调用内核函数的一个方式了呵呵

if (state != TASK_RUNNING)               //  这里判断了,原来只要是就绪态的都不打印,还是比较恶心的。我前面的描述有误
                show_stack(p, NULL);


不知道为什么一定要把这些进程去掉,不过前面好像打印出了PC值,还是有一些信息。

我试了一把,大多数进程还是不处于TASK_RUNNING状态的,当然是在机器比较闲的时候呵呵
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP