2012-09-20 96 views
0

生成函數調用對於C

我用-finstrument-functions來產生進入和我的每個函數調用的退出信息,並使用點繪製它只是像上面。但是,我發現一個問題,在我的main函數中,我創建了兩個線程,一個名爲driver_TASL,另一個是keyBoard_TASK。但在我生成的圖片中,看起來好像我的keyBoard_TASKdriver_TASK調用。它應該像這兩個任務由main

備註叫:我不能上傳圖片,所以我形容它下面:

我生成函數調用之後,它應該是這樣的:

  • main通話driver_TASK
  • main呼叫keyBoard_TASK

然而,就變成

  • main呼叫driver_TASK
  • driver_TASK呼叫keyboard_TASK

爲什麼keyBoard_TASKdriver_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"] 

} 
+5

你的問題到底是什麼? –

+0

對不起,我不能上傳圖片... –

+0

我的問題是爲什麼函數跟蹤器告訴我,'driver_TASK'調用的'keyBoard_TASK' –

回答

2

我假設您使用the 'instrumental' library來收集通話圖表信息(如果沒有,您應該在__cyg_profile_func_enter()__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() 

當真的應該爲每個線程(這將需要在儀器中的線程感知)單獨的調用圖。爲了解決這個問題,你需要做以下之一:

  • 找到一個儀器庫的線程知道
  • 新增主題的認識到一個你使用現在
  • 解決了產生手動記錄(如果線程功能相對簡單,這可能很簡單,但可能會變成大型/複雜的任務)
+0

乾杯!感謝您的幫助 –

0

問題必須在你如何測試函數。嚴格地說,main沒有調用這些函數中的任何一個;啓動線程不等同於函數調用。你的兩個函數都應該只顯示一些系統函數作爲調用者。 main不在其調用堆棧中。

現在main和你的兩個函數之間的關係是一個特殊的依賴關係,你應該以某種方式跟蹤不同的方式。

+0

感謝您的評論,我可以理解,我的'driver_TASK'和'keyBoard_TASK '由'pthread_create'調用 –

+0

不,他們不是「被調用」的。 'pthread_create'發生在'main'的線程內部。這兩個線程由系統內核啓動,它們的調用棧中既沒有'main'也沒有''pthread_create''。 –