Ker*_* SB 22 c c++ linux coredump pthreads
在这里和这里之前已经提出了与这个问题中的一个相似的点,并且我知道Google coredump库(我已经评估并发现它缺乏,但是如果我更好地理解这个问题,我可能会尝试并努力).
我想在不中断进程的情况下获取正在运行的Linux进程的核心转储.自然的方法是说:
if (!fork()) { abort(); }
Run Code Online (Sandbox Code Playgroud)
由于分叉进程获得原始进程内存的固定快照副本,因此我应该获得完整的核心转储,并且由于副本使用写时复制,因此通常应该很便宜.但是,这种方法的一个关键缺点是fork()
只分叉当前线程,并且原始进程的所有其他线程将不存在于分叉副本中.
我的问题是,是否有可能以某种方式获得其他原始线程的相关数据.我不完全确定如何解决这个问题,但这里有几个我提出的子问题:
包含所有线程堆栈的内存是否仍然可用并在分叉进程中可访问?
是否可以(快速)枚举原始进程中的所有正在运行的线程并存储其堆栈基址的地址?据我了解,Linux上的线程堆栈的基础包含指向内核的线程簿记数据的指针,所以......
使用存储的线程基地址,您能读出分叉进程中每个原始线程的相关数据吗?
如果可能,也许只需要将其他线程的数据附加到核心转储.但是,如果该数据已经在fork的位置丢失,那么这种方法似乎没有任何希望.
Nom*_*mal 14
您熟悉流程检查点重启吗?CRIU特别是?在我看来,它可能为您提供一个简单的选择.
我想获得正在运行的Linux进程的核心转储,而不会中断进程[和]以某种方式获取其他原始线程的相关数据.
忘记不要打断这个过程.如果你考虑一下,核心转储必须在转储期间中断进程; 因此,您的真正目标必须是尽量减少这种中断的持续时间.您最初使用的想法fork()
确实会中断该过程,它只会在很短的时间内完成.
- 包含所有线程堆栈的内存是否仍然可用并在分叉进程中可访问?
fork()
不会.唯一保留执行实际调用的线程,其余线程的堆栈将丢失.
这是我使用的程序,假设CRIU不合适:
有一个父进程,只要子进程停止,就会生成子进程的核心转储.(注意,可能会生成多个连续的停止事件;只有第一个停止事件才会被执行.)
您可以使用检测停止/继续事件waitpid(child,,WUNTRACED|WCONTINUED)
.
可选:用于sched_setaffinity()
将进程限制为单个CPU,并且sched_setscheduler()
(可能sched_setparam()
)将进程优先级降低到IDLE
.
您可以从父进程执行此操作,该进程只需要CAP_SYS_NICE
能力(您可以将其setcap 'cap_sys_nice=pe' parent-binary
用于父二进制文件,如果您启用了像大多数当前Linux发行版那样的文件系统功能),在有效和允许的集合中都可以.
目的是在线程决定它想要快照/转储的时刻和所有线程停止的时刻之间最小化其他线程的进度.我还没有测试过更改生效所需的时间 - 当然它们最早只发生在当前时间段的末尾.所以,这个步骤应该事先做好一点.
就个人而言,我不打扰.在我的四核机器上,以下SIGSTOP
单独产生线程之间的延迟类似于互斥锁或信号量,所以我认为没有必要争取更好的同步.
当子进程中的一个线程决定它想要拍摄自己的快照时,它会向SIGSTOP
自己发送一个(via kill(getpid(), SIGSTOP)
).这将停止进程中的所有线程.
父进程将收到子进程已停止的通知.它将首先检查/proc/PID/task/
获取子进程的每个线程的TID(并且可能/proc/PID/task/TID/
是其他信息的伪文件),然后使用附加到每个TID ptrace(PTRACE_ATTACH, TID)
.显然,ptrace(PTRACE_GETREGS, TID, ...)
将获得每线程寄存器状态,它可以与每个线程堆栈跟踪一起使用/proc/PID/task/TID/smaps
并/proc/PID/task/TID/mem
获得每个线程堆栈跟踪,以及您感兴趣的任何其他信息.(例如,您可以创建兼容调试器的核心每个帖子的文件.)
当父进程完成抓取转储时,它允许子进程继续.我相信你需要发送一个单独的SIGCONT
信号让整个子进程继续,而不仅仅是依赖ptrace(PTRACE_CONT, TID)
,但我没有检查过这个; 请验证这一点.
我确实认为,上述过程将停止进程中线程之间的挂钟时间的最小延迟.在Xubuntu和3.8.0-29通用内核上对AMD Athlon II X4 640进行快速测试表明在其他线程中增加一个volatile变量的紧密循环只会使计数器增加几千,这取决于线程的数量(这里有太多我做的几个测试中的噪音更具体的说法.
将进程限制为单个CPU,甚至限制为IDLE优先级,将进一步大幅减少延迟.CAP_SYS_NICE
功能允许父母不仅降低子进程的优先级,而且还将优先级提升回原始级别; 文件系统功能意味着父进程甚至不必是setuid,因为CAP_SYS_NICE
单独就足够了.(我认为它足够安全 - 在父程序中有一些好的检查 - 安装在大学计算机中,学生们非常积极地找到有趣的方法来利用已安装的程序.)
可以创建一个提供增强功能的内核补丁(或模块),kill(getpid(), SIGSTOP)
它也试图从运行的CPU中启动其他线程,从而尝试使线程之间的延迟停止更小.就个人而言,我不会打扰.即使没有CPU /优先级操作,我也可以获得足够的同步(线程停止之间的延迟足够小).
您是否需要一些示例代码来说明我的想法?