我如何从序列输出中确定程序的哪一部分没有获得互斥锁?
How do I determine from strace output what part of my program is failing to acquire a mutex
我正在一个嵌入式Linux系统(3.12.什么的)上工作,我们的应用程序在一段随机的时间后开始占用CPU。我在应用程序上运行了strace
,当问题发生时,我在strace
输出中看到了许多类似的行:
[48530666] futex(0x485f78b8, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable) <0.009002>
我很确定这就是我要找的确凿证据,这是一场比赛。然而,我现在需要弄清楚如何识别代码中试图获得这个互斥锁的位置。我该怎么做呢?我们的代码是用GCC编译的,里面有调试符号。
我目前的想法(我还没有尝试过)是在试图在我们的系统中抓取任何互斥之前打印出一个字符串到stdout和flush,期望字符串将在strace抱怨获得锁之前打印出来…但是代码中有很多地方需要像这样进行检测。
编辑:我刚刚意识到的另一件奇怪的事情是,我们的程序不会开始占用CPU,直到一些随机的时间已经过去,因为它运行(5分钟到5小时之间的任何地方)。在此期间,发生的 0 futex
系统调用。为什么他们突然开始?从我所读到的,我认为也许它们在用户空间中被正确使用,直到某些东西失败并回落到使futex()
系统调用…
有什么建议吗?
如果您经常在短时间内永久锁定来自不同线程的互斥锁,例如保护全局记录器的互斥锁,则可能会导致所谓的线程护航。直到两个线程竞争锁时才会出现问题。第一个进程获得锁并持有它一段时间,然后,当它第二次需要锁时,它被抢占,因为第二个进程已经在等待。第二个也是一样。每个线程可用的时间片突然减少到两次锁尝试之间的时间,导致许多上下文切换和相应的速度减慢。此外,除了一个线程之外,所有线程总是在互斥锁上被阻塞,有效地禁用了任何并行执行。
为了解决这个问题,让你的线程合作而不是竞争资源。对于上面的日志记录器示例,可以考虑为条目使用无锁队列,或者使用线程本地存储为每个线程使用单独的队列。
关于futex()调用,这个想法是轮询一个原子标志,在一些旋转之后使用实际的操作系统互斥锁。原子标志不需要在用户空间和内核空间之间进行昂贵的切换。对于较长的中断,使用内核抢占(futex()
)可以避免轮询阻塞CPU。这解释了为什么程序在正常操作中不需要任何futex()
调用。
你,此时基本上需要生成核心文件。
然后你可以在GDB中加载program+core并查看它
man gcore
或
generate-core-file
在此期间,没有发生futex系统调用。为什么他们突然开始?
这是由于通过futex实现的无争用互斥锁不进行系统调用,只在用户空间进行原子增量。只有当系统调用
- Mongodb c++驱动程序:如何查询元素的数组
- C++,系统无法执行指定的程序
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到
- 重载操作程序时出错>>用于类中的字符串 memebr
- 我可以将c ++清理器仅应用于程序的一部分而不是第三方库吗?
- c++中的交叉编译(作为跨平台应用程序的一部分或作为服务)
- Makefile:编译一个llvm程序,作为g++编译的bnfc项目的一部分
- C++,我怎样才能在继续整个程序的同时延迟程序的一部分
- Windows App:仅在应用程序的一部分中渲染DirectX
- C++的新手,程序在取消引用向量的一部分时没有响应
- 是否可以在程序中使用 std::string 作为 if else 语句的一部分
- 将其他程序用作另一个程序的一部分
- 通过GPU计算并行程序的一部分的可能选项
- 我如何从序列输出中确定程序的哪一部分没有获得互斥锁?
- 我在 c++ 代码的这一部分中找不到第二个常量实用程序,有人可以解释一下吗?
- 程序的一部分在首次运行后未执行
- 运行时解释器真的是 C 程序执行的一部分吗?
- 如何强制程序的一部分只运行一次