2010-07-13 42 views
1

我需要編寫一個日誌API,它可以在單獨的線程上進行實際日誌記錄。捕獲調用堆棧,並讓它在不同的線程中執行

即我有一個想要記錄一些信息的應用程序。它調用我的API並且api捕獲所有的參數等,然後把它交給一個單獨的線程進行記錄。

記錄器API接受可變參數,因此我最初的想法是捕獲整個調用堆棧,並以某種方式將它交給將執行日誌記錄的線程。

我很高興能夠捕獲到調用堆棧。不過,我不確定我是如何將這個調用堆棧傳遞給另一個方法的。

我在linux上使用g ++,它可能還必須在solaris上使用Sun的CC v12。

任何想法。

回答

2

您可以在調用堆棧上捕獲固定數量的字節,但即使不需要時也必須複製所有內存,並將其放入某種類型的隊列以將其傳遞到日誌記錄線程。似乎有很多工作要做,而且效率很低。

我假設你正在使用一個單獨的日誌記錄線程來提高日誌API的效率。在這種情況下,使日誌API提取可變參數並將其轉換爲更簡單的表示(例如要記錄的字符串)並對其進行排隊是非常有效的。

還要注意一個好的日誌API不應該阻塞,所以我建議在日誌API和日誌記錄線程之間建立一個無鎖隊列。

+0

感謝弗雷德裏克。這確實是線程記錄器背後的基本原理。我想把磁盤io的緩慢工作轉移到另一個線程上。 我試着複製堆棧,但當然這仍然意味着所有正在被記錄的對象必須有足夠長的時間才能被記錄。我認爲你是在調用點構建日誌字符串的方法,然後把它交給記錄器是一種更好的方法。 – ScaryAardvark 2010-07-13 10:34:21

0

問題是你不知道如何把它交給另一個線程,最簡單的事情是讓一個隊列(std :: deque,可能)的調用堆棧與一個互斥體保護它。當你的應用程序生成一個調用堆棧時,它會鎖定互斥鎖,推動調用堆棧,並解鎖互斥鎖。日誌記錄線程定期鎖定互斥鎖,檢查隊列的大小,如果它不爲空,則關閉一個callstack並對其進行處理。有些方法可以提高那裏的效率(例如,條件變量,使用單獨的計數器,因此在檢查大小之前不必鎖定,或者甚至使用非鎖定的數據結構),但我會建議不要擔心直到他們出現在分析中。

0

替代方法可以是:

  1. 定義哪些打印功能名稱,並使用標準的預定義的宏像文件名,行號等一些附加信息的宏。你甚至可以傳遞一些額外的日誌信息,否則你將使用printf。這將調用函數將數據發送到其他線程。該線程可以在套接字/管道上等待。將數據寫入該數據,然後可以使用系統調用(寫入/讀取/管道)讀取數據。
  2. 現在在每個函數/ API的開始插入此宏。您可以獲得呼叫流程(調用堆棧)
  3. 然後您的日誌記錄線程可以使用此宏中的信息寫入文件,在控制檯等上顯示。

    限定PRINT_LOG(X)function_to_pass_data_to_thread(X,FILELINE);

    API1() 
    { 
        PRINT_LOG("Entered API1"); 
        //Your API here 
    

    }

PS:抱歉以次充好編輯。我似乎無法理解編輯今天的問題。需要記錄一個SO錯誤,我猜;)

相關問題