如何在Linux利用Pstack打印多线程程序在响应卡顿时的内核层级实时调用栈

星雪吖_7686

星雪吖_7686

2026-06-09

1079人浏览

原创

pstack仅显示用户态调用栈,无法呈现内核态路径;若栈顶为epoll_wait、read等系统调用封装函数,可判定线程阻塞在内核态,需结合/proc/pid/status、perf或/proc/pid/stack进一步验证。

如何在linux利用pstack打印多线程程序在响应卡顿时的内核层级实时调用栈

pstack 本身不打印内核层级调用栈,它只显示用户态函数调用栈(即应用代码、glibc、pthread 等在用户空间的执行路径)。所谓“内核层级实时调用栈”,比如 epoll_wait 在内核中实际卡在哪条路径、是否在 __x64_sys_epoll_wait → do_epoll_wait → ep_poll → schedule_timeout 中挂起,pstack 完全无法呈现——它看到的只是用户态系统调用入口(如 #0 in epoll_wait() from libc.so.6),后面全是黑盒。

但你可以结合 pstack 的输出 + 其他机制,间接定位多线程程序在响应卡顿时是否卡在内核态,以及大概卡在什么系统调用环节。关键在于:识别线程状态 + 匹配常见内核等待点 + 补充验证手段。


? 怎么从 pstack 输出判断线程是否卡在内核态?

pstack 显示的是 当前用户态栈顶帧,而很多阻塞系统调用(如 epoll_wait、read、accept、pthread_cond_wait、nanosleep)在进入内核后,用户栈就停在 libc 的封装函数里。只要看到以下典型帧,基本可判定线程正阻塞在内核态:

  • epoll_wait()、poll()、select()
  • read()、write()、recvfrom()、sendto()(尤其对 socket 或 pipe)
  • accept()、connect()
  • pthread_cond_wait()、sem_wait()(背后是 futex 系统调用)
  • nanosleep()、clock_nanosleep()
  • waitpid()、wait4()

例如:

Thread 2 (LWP 1235):
#0 0x00007f8a1b2c3a60 in __epoll_pwait () from /lib64/libc.so.6
#1 0x0000000000402a1c in event_loop () at server.c:92

→ 这说明该线程正在内核 epoll 机制中等待事件,尚未返回用户态,属于健康等待;若所有工作线程都卡在这里,而业务无请求进来,则可能是前端断连或负载均衡问题。

反之,若看到:

Thread 3 (LWP 1236):
#0 0x00007f8a1b2c1234 in __lll_lock_wait () from /lib64/libpthread.so.0
#1 0x00007f8a1b2be9a5 in pthread_mutex_lock () from /lib64/libpthread.so.0
#2 0x0000000000403c8d in handle_request () at server.c:215

→ 这属于用户态锁竞争(futex 在内核协助,但阻塞根源是用户代码未释放 mutex),需查死锁或临界区过长。

Linux Distros
Linux Distros

Linux发行版游乐场,适用于需要临时Linux沙箱、基于浏览器的Linux虚拟机、一次性终端环境、桌面Linux会话等场景

下载

? 如何补充验证“是否真卡在内核”及具体位置?

pstack 不够,需搭配以下低侵入手段:

  • 看 /proc/<pid>/stack</pid>(仅限内核线程或开启 CONFIG_PROC_KCORE 的 kernel)
    普通用户进程不支持,但部分较新内核(≥5.10)且启用了 CONFIG_PROC_STACKS 时,可尝试:

    cat /proc/1234/stack  # 若返回 Permission denied 或空,说明不可用

    ✅ 成功时会显示类似:

    [<ffffffff810a1234>] __schedule+0x2a4/0x750
    [<ffffffff810a189a>] schedule+0x3a/0x90
    [<ffffffff810a5abc>] do_wait+0x1fc/0x260
    [<ffffffff810a6123>] kernel_wait4+0x93/0x110
    [<ffffffff81023456>] sys_wait4+0x66/0xf0
    [<ffffffff818002ab>] system_call_fastpath+0x22/0x27</ffffffff818002ab></ffffffff81023456></ffffffff810a6123></ffffffff810a5abc></ffffffff810a189a></ffffffff810a1234>

    ⚠️ 注意:这仍是内核线程视角,普通进程无法直接映射到其 syscall 入口细节。

  • 用 perf 抓内核上下文采样(推荐)
    不依赖 ptrace,无 attach 风险,能反映真实内核函数热点:

    # 采样 5 秒,聚焦该进程的内核态栈
    perf record -e 'syscalls:sys_enter_*' -p 1234 -- sleep 5
    perf script | grep -E "(epoll_wait|read|futex)" | head -20
    # 或直接看内核调用栈(需 debuginfo)
    perf record -e sched:sched_switch -p 1234 -g -- sleep 5
    perf report --no-children -s symbol
  • 检查 /proc/<pid>/status</pid> 中的 State 和 voluntary_ctxt_switches

    grep -E "State|ctxt" /proc/1234/status

    若 State: S(可中断睡眠)且 voluntary_ctxt_switches 长时间不增长 → 很可能卡在不可中断路径(如 D 状态,但 pstack 本就 attach 失败);若 State: R(运行)但 CPU 占用高 → 查用户态循环;若 State: D → pstack 必失败,需用 ps 或 cat /proc/1234/stack(仅限 kernel thread)确认。


⚠️ pstack 自身限制与绕过建议

  • D 状态进程:pstack 直接报 Cannot attach to process,此时无法用任何 ptrace 工具(包括 gdb)获取栈,只能靠 ps、top、/proc/<pid>/status</pid> 判断是否卡在磁盘 I/O 或 NFS。
  • 权限不足:非属主或非 root 无法 attach → 改用 sudo pstack 1234,或提前部署 ptrace_scope=0(不推荐生产)。
  • 符号缺失导致 ??() 太多:安装对应 debuginfo 包(如 glibc-debuginfo, libstdc++-debuginfo),或用:
    gdb -p 1234 -ex "set debug-file-directory /usr/lib/debug" -ex "thread apply all bt" -ex "detach" -ex "quit"

不复杂但容易忽略:pstack 是诊断起点,不是终点。它告诉你“线程停在哪一行用户代码”,而真正卡在哪一层内核,得靠 perf + /proc + 状态交叉印证。

相关文章

全能打印神器
全能打印神器

全能打印神器是一款非常好用的打印软件,可以在电脑、手机、平板电脑等设备上使用。支持无线打印和云打印,操作非常简单,使用起来也非常方便,有需要的小伙伴快来保存下载体验吧!

下载

相关标签:

linux

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
磁盘配额是什么
磁盘配额是什么

磁盘配额是计算机中指定磁盘的储存限制,就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间。php中文网为大家提供各种磁盘配额相关的内容,教程,供大家免费下载安装。

2023.06.21

3930

4

如何安装LINUX
如何安装LINUX

本站专题提供如何安装LINUX的相关教程文章,还有相关的下载、课程,大家可以免费体验。

2023.06.29

3373

10

linux find
linux find

find是linux命令,它将档案系统内符合 expression 的档案列出来。可以指要档案的名称、类别、时间、大小、权限等不同资讯的组合,只有完全相符的才会被列出来。find根据下列规则判断 path 和 expression,在命令列上第一个 - ( ) , ! 之前的部分为 path,之后的是 expression。还有指DOS 命令 find,Excel 函数 find等。本站专题提供linux find相关教程文章,还有相关

2023.06.30

2513

5

linux修改文件名
linux修改文件名

本专题为大家提供linux修改文件名相关的文章,这些文章可以帮助用户快速轻松地完成文件名的修改工作,大家可以免费体验。

2023.07.05

6090

7

linux系统安装教程
linux系统安装教程

linux系统是一种可以免费使用,自由传播,多用户、多任务、多线程、多CPU的操作系统。本专题提供linux系统安装教程相关的文章,大家可以免费体验。

2023.07.06

5722

7

linux查看文件夹大小
linux查看文件夹大小

Linux是一种自由和开放源码的类Unix操作系统,存在着许多不同的Linux版本,但它们都使用了Linux内核。Linux可安装在各种计算机硬件设备中,比如手机、平板电脑、路由器、视频游戏控制台、台式计算机、大型机和超级计算机。linux怎么查看文件夹大小呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.07.20

3353

8

linux查看ip命令
linux查看ip命令

本专题为大家提供linux查看ip命令相关文章内容,感兴趣的朋友可以免费下载体验试试。

2023.07.20

2865

4

linux查看cpu使用率
linux查看cpu使用率

在linux的系统维护中,可能需要经常查看cpu使用率,分析系统整体的运行情况。本专题为大家带来了linux查看cpu使用率的相关文章,感兴趣的朋友千万不要错过了。

2023.07.25

3079

6

linux查找文件命令
linux查找文件命令

Linux是一种自由和开放源码的类Unix操作系统,存在着许多不同的Linux版本,但它们都使用了Linux内核。Linux可安装在各种计算机硬件设备中,比如手机、平板电脑、路由器、视频游戏控制台、台式计算机、大型机和超级计算机。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.07.31

297

3

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Buffalo框架快速入门指南
Buffalo框架快速入门指南

共0课时 | 0人学习

Valgrind支持平台说明
Valgrind支持平台说明

共0课时 | 0人学习