我正在调试一个多线程的Linux进程,其中某个线程似乎在几秒钟内没有运行。查看strace输出发现它在等待futex,例如:
1673109 14:36:28.600329 futex(0x44b8d20, FUTEX_WAIT_PRIVATE,
1673109 14:36:33.221850 <... futex resumed> ) = 0 <4.621514>
如何找出这个futex(0x44b8d20)在用户空间中对应的是什么锁定构造,即如何将其映射到内部使用futex的锁定构造。
我正在调试一个多线程的Linux进程,其中某个线程似乎在几秒钟内没有运行。查看strace输出发现它在等待futex,例如:
1673109 14:36:28.600329 futex(0x44b8d20, FUTEX_WAIT_PRIVATE,
1673109 14:36:33.221850 <... futex resumed> ) = 0 <4.621514>
如何找出这个futex(0x44b8d20)在用户空间中对应的是什么锁定构造,即如何将其映射到内部使用futex的锁定构造。
futex()
系统调用的第一个参数。
如果您的系统上已安装SystemTap,
只需启动此SystemTap脚本:stap futexes.stp
如果链接不可用,请参考以下脚本:
#! /usr/bin/env stap
# This script tries to identify contended user-space locks by hooking
# into the futex system call.
global FUTEX_WAIT = 0 /*, FUTEX_WAKE = 1 */
global FUTEX_PRIVATE_FLAG = 128 /* linux 2.6.22+ */
global FUTEX_CLOCK_REALTIME = 256 /* linux 2.6.29+ */
global lock_waits # long-lived stats on (tid,lock) blockage elapsed time
global process_names # long-lived pid-to-execname mapping
global entry_times%, uaddrs%
probe syscall.futex {
if ((op & ~(FUTEX_PRIVATE_FLAG|FUTEX_CLOCK_REALTIME)) != FUTEX_WAIT) next
entry_times[tid()] = gettimeofday_us()
uaddrs[tid()] = futex_uaddr
}
probe syscall.futex.return {
if (!(entry_times[tid()])) next
elapsed = gettimeofday_us() - entry_times[tid()]
lock_waits[pid(), uaddrs[tid()]] <<< elapsed
delete entry_times[tid()]
delete uaddrs[tid()]
if (!(pid() in process_names))
process_names[pid()] = execname()
}
probe end {
foreach ([pid+, lock] in lock_waits)
printf ("%s[%d] lock %p contended %d times, %d avg us\n",
process_names[pid], pid, lock, @count(lock_waits[pid,lock]),
@avg(lock_waits[pid,lock]))
}
sudo ./futexes.stp
时遇到了问题。 语义错误:解析探测点时:'syscall'标识符在./futexes.stp:15:7处 源:probe >syscall.futex {语义错误:无匹配项第2遍:分析失败。[man error :: pass2] 类似错误消息的数量被抑制:1。 使用-v重新运行以查看它们。 - ThorSummonersystemtap
工具运行futexes.stp
脚本。在 Ubuntu 上可以使用apt-get install systemtap
安装,然后以 root 用户身份执行stap futexes.stp
命令。更多信息请参见:https://sourceware.org/systemtap/SystemTap_Beginners_Guide/using-systemtap.html - dpoggi