使用场景(个人场景):
在 图像处理过程中,在不挂载gdb的情况下,将内存中的数据导出出来(导出的动作程序中已经写好)
如:
...
if (b_out2disk)
{
// 数据或者图像导出到磁盘
}
...
我们使用signal来控制“b_out2disk”,从而可以灵活的操作:
#include <iostream>
#include <signal.h>
#include <thread>
bool g_b_out2disk = false;
void signal_start()
{
g_b_out2disk = true;
}
void signal_end()
{
g_b_out2disk = false;
}
int main()
{
// 关键部分
signal(63, signal_start);
signal(64, signal_end);
while(true)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}
完成类似上述代码,就可以通过:
kill -63 pid 来打开开关
kill -64 pid 来关闭开关
另外一种方式:
上面这种方式缺点就是需要显式的在main函数内部侵入代码,这样不太好,最近看leakTracer源码,里面的方式类似下面这种
#include <cstring>
#include <iostream>
#include <dlfcn.h>
#include <signal.h>
void test_sig1(int sigNumber, siginfo_t *siginfo, void *arg)
{
printf("=====sig...act1\n");
}
void test_sig2(int sigNumber, siginfo_t *siginfo, void *arg)
{
printf("=====sig...act2\n");
}
int signalNumberFromString(const char* signame)
{
int sigNumber = 1;
if (strcmp(signame, "USR1") == 0)
sigNumber = SIGUSR1;
else if (strcmp(signame, "USR2") == 0)
sigNumber = SIGUSR2;
else
sigNumber = SIGUSR1
if (sigNumber == SIGUSR1)
{
struct sigaction sigact;
sigact.sa_sigaction = test_sig1;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_SIGINFO;
sigaction(sigNumber, &sigact, NULL);
}
else if(sigNumber == SIGUSR2)
{
struct sigaction sigact;
sigact.sa_sigaction = test_sig2;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_SIGINFO;
sigaction(sigNumber, &sigact, NULL);
}
return 1;
}
__attribute__ ((constructor)) void MemoryTraceOnInit(void)
{
if (getenv("LEAKTRACER_ONSIG_STARTALLTHREAD"))
{
signalNumberFromString(getenv("LEAKTRACER_ONSIG_STARTALLTHREAD"));
}
if (getenv("LEAKTRACER_ONSIG_REPORT"))
{
signalNumberFromString(getenv("LEAKTRACER_ONSIG_REPORT"));
}
}
代码可能有点混乱,体会精神即可