我使用-finstrument-functions
生成每个函数调用的输入和退出信息,并使用点来绘制它,就像上面一样。但是,我发现了一个问题,在我的main
函数中,我创建了两个线程,一个叫做driver_TASL,另一个是keyBoard_TASK。但是在我生成的图片中,似乎我的keyBoard_TASK
被driver_TASK
调用了。它应该像main
备注:我无法上传图片,因此我在下面对其进行描述:
生成函数调用后,它应该是:
main
致电driver_TASK
main
致电keyBoard_TASK
main
致电driver_TASK
driver_TASK
致电keyboard_TASK
为什么keyBoard_TASK
被driver_TASK
调用了?它应该由main
调用
在我的源代码中,我写了它们(我在代码中删除了一些打印函数):
int main(/*@ unused @*/int argc, /*@ unused @*/char *argv[]) //comment for lint
{
int res;
pthread_t driver_thread, keyBoard_thread;
void *thread_result;
res = pthread_create(&driver_thread, NULL, driver_TASK, (void *)&_gDriverStatus);
if(res != 0)
{
perror("Thread Creation Failed");
exit(EXIT_FAILURE);
}
sleep(1);
res = pthread_create(&keyBoard_thread, NULL, keyBoard_TASK, (void *)&_gKeyStatus);
if(res != 0)
{
perror("Thread Creation Failed");
exit(EXIT_FAILURE);
}
res = pthread_join(driver_thread, &thread_result);
if(res != 0)
{
perror("Thread Join Failed");
exit(EXIT_FAILURE);
}
res = pthread_join(keyBoard_thread, &thread_result);
if(res != 0)
{
perror("Thread Join Failed");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
我还附加了我的自动点文件,函数调用流程图由pvtace自动生成
digraph DEMO {
main [shape=rectangle]
driver_TASK [shape=rectangle]
DDI_DRIVER_Probe [shape=rectangle]
_Driver_Clear [shape=ellipse]
_Driver [shape=ellipse]
DRIVER_Probe_Demo [shape=ellipse]
DDI_DRIVER_Init [shape=rectangle]
DRIVER_Init_Demo [shape=rectangle]
_DRIVER_Init_Demo [shape=ellipse]
DDI_DRIVER_Running [shape=rectangle]
DRIVER_Running_Demo [shape=rectangle]
_DRIVER_Running_Demo [shape=ellipse]
keyBoard_TASK [shape=rectangle]
main -> DBG_PrintColor [label="2 calls" fontsize="10"]
main -> driver_TASK [label="1 calls" fontsize="10"] //this is correct
driver_TASK -> DBG_PrintColor [label="6 calls" fontsize="10"]
driver_TASK -> DDI_DRIVER_Probe [label="1 calls" fontsize="10"]
driver_TASK -> DDI_DRIVER_Init [label="1 calls" fontsize="10"]
driver_TASK -> DDI_DRIVER_Running [label="1 calls" fontsize="10"]
driver_TASK -> keyBoard_TASK [label="1 calls" fontsize="10"] //this is not correct
DDI_DRIVER_Probe -> _Driver_Clear [label="1 calls" fontsize="10"]
DDI_DRIVER_Probe -> _Driver [label="1 calls" fontsize="10"]
DDI_DRIVER_Probe -> DRIVER_Probe_Demo [label="1 calls" fontsize="10"]
DDI_DRIVER_Init -> _Driver [label="1 calls" fontsize="10"]
DDI_DRIVER_Init -> DRIVER_Init_Demo [label="1 calls" fontsize="10"]
DRIVER_Init_Demo -> _DRIVER_Init_Demo [label="1 calls" fontsize="10"]
DDI_DRIVER_Running -> _Driver [label="1 calls" fontsize="10"]
DDI_DRIVER_Running -> DRIVER_Running_Demo [label="1 calls" fontsize="10"]
DRIVER_Running_Demo -> _DRIVER_Running_Demo [label="1 calls" fontsize="10"]
keyBoard_TASK -> DBG_PrintColor [label="6 calls" fontsize="10"]
}
答案 0 :(得分:2)
我假设您使用the 'instrumental' library来收集调用图信息(如果没有,您应该在__cyg_profile_func_enter()
和{{1}中指明您正在使用的内容和/或您在做什么例程)。
查看实现(在http://www.suse.de/~krahmer/instrumental/处可用),很明显调用图信息不是以线程安全的方式收集的。调用的每个函数只是在调用时记录在日志文件中,调用图的深度保存在全局变量中(实际上是静态变量)。有关调用链的信息也保存在全局数组中。
所以发生的事情是发生以下事件:
__cyg_profile_func_exit()
这些事件碰巧按此顺序发生,而没有介入__cyg_profile_func_enter() - for main() on main thread
__cyg_profile_func_enter() - for driver_TASK() on driver_thread
__cyg_profile_func_enter() - for keyBoard_TASK() on keyboard_thread
...
事件,这意味着工具库记录的内容如同:
__cyg_profile_func_exit()
当每个线程确实应该有单独的调用图时(这需要在检测中使用线程感知)。要解决此问题,您需要执行以下操作之一:
答案 1 :(得分:0)
问题必须在于如何检测功能。严格来说,main
并未调用这些函数中的任何一个;启动线程并不等同于函数调用。您的两个函数都应该只显示一些系统函数作为调用者。 main
不在他们的通话堆栈中。
现在main
和你的两个函数之间的关系是一个特殊的依赖关系,你应该以某种方式跟踪它。