0

我使用-finstrument-functions生成每个函数调用的进入和退出信息,并使用点来绘制它,就像上面一样。但是,我发现了一个问题,在我的main函数中,我创建了两个线程,一个叫 driver_TASL,另一个叫 keyBoard_TASK。但在我生成的图片中,似乎我的keyBoard_TASK被调用了driver_TASK。应该像这两个 TASK 所调用的main

备注:我不能上传图片,所以我在下面描述它:

在我生成函数调用后,它应该是这样的:

  • main称呼driver_TASK
  • main称呼keyBoard_TASK

然而,它变成

  • main称呼driver_TASK
  • driver_TASK称呼keyboard_TASK

为什么keyBoard_TASK被调用driver_TASKmain我认为它应该被称为

在我的源代码中,我把它们写成这样(我在代码中删除了一些打印函数):

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"]

}
4

2 回答 2

2

我假设您正在使用“工具”库__cyg_profile_func_enter()来收集调用图信息(如果没有,您应该指出您正在使用什么和/或您在and__cyg_profile_func_exit()例程中做了什么)。

查看实现(可在http://www.suse.de/~krahmer/instrumental/获得),很明显调用图信息不是以线程安全的方式收集的。每个被调用的函数在被调用时都简单地记录在日志文件中,调用图的深度保存在一个全局变量(实际上是一个静态变量)中。有关调用链的信息也保存在一个全局数组中。

所以发生的事情是发生了以下事件:

__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()事件,这意味着器乐库记录的事情就像:

main()
|
+--- driver_TASK()
     |
     +--- keyBoard_TASK()

当每个线程真的应该有单独的调用图时(这将需要检测中的线程意识)。要解决此问题,您需要执行以下操作之一:

  • 找到一个线程感知的仪器库
  • 为您现在使用的线程添加线程感知
  • 手动修复生成的日志(如果线程功能相对简单,这可能很简单,但结果可能是一项大型/复杂的任务)
于 2012-09-20T08:20:54.583 回答
0

问题必须在于您如何检测功能。严格来说,main不是调用这些函数中的任何一个;启动线程不等同于函数调用。您的两个函数都应该只显示一些系统函数作为它们的调用者。main不在他们的调用堆栈上。

现在main你的两个函数之间的关系是一个特殊的依赖关系,你应该以不同的方式跟踪它。

于 2012-09-20T08:00:24.643 回答