国产一级一区二区_segui88久久综合9999_97久久夜色精品国产_欧美色网一区二区

掃一掃
關注微信公眾號

在多線程應用程序中進行日志記錄
2008-07-11   IBM

沒有任何軟件是完全沒有錯誤的,在程序的運行期間,應用程序用戶可能會碰到意想不到的結果。要分析并找出導致這些問題的原因,程序員所廣泛使用的一種方法就是日志記錄。在本文中,您將了解如何使用循環緩沖區通過內存操作(而不是文件操作)高效地進行日志記錄。為該緩沖區選擇合適的大小,從而確保轉儲相關的消息,這將在調試時很有幫助。

引言

“如果有兩種方式可以編寫出沒有錯誤的程序,那么只有第三種方式是有效的。” —Alan J. Perlis

在關鍵的計算機應用程序的生存期中,日志記錄是一件非常重要的活動,特別是當故障的癥狀并不十分明顯時。日志記錄提供了故障前應用程序狀態的詳細信息,如變量的值、函數的返回值等等。在一段時間的運行過程中,將不斷地產生大量的跟蹤數據,并持續地將其寫入到磁盤上的文本文件中。要進行有效的日志記錄,需要使用大量的磁盤空間,并且在多線程環境中,所需的磁盤空間會成倍地增加,因為大量的線程都在記錄它們的跟蹤信息。

使用常規文件進行日志記錄的兩個主要問題是:硬盤空間的可用性,以及在對一個文件寫入數據時磁盤 I/O 的速度較慢。持續地對磁盤進行寫入操作可能會極大地降低程序的性能,導致其運行速度緩慢。通常,可以通過使用日志輪換策略來解決空間問題,將日志保存在幾個文件中,當這些文件大小達到某個預定義的字節數時,對它們進行截斷和覆蓋。

要克服空間問題并實現磁盤 I/O 的最小化,某些程序可以將它們的跟蹤數據記錄在內存中,僅當請求時才轉儲這些數據。這個循環的、內存中的緩沖區稱為循環緩沖區。本文討論了循環緩沖區的一些常見實現,并對多線程程序中循環緩沖區的啟用機制提出了一些觀點。

循環緩沖區

循環緩沖區是一種用于應用程序的日志記錄技術,它可以將相關的數據保存在內存中,而不是每次都將其寫入到磁盤上的文件中。在需要的時候(比如當用戶請求將內存數據轉儲到文件中時、程序檢測到一個錯誤時,或者由于非法的操作或者接收到的信號而引起程序崩潰時)可以將內存中的數據轉儲到磁盤。循環緩沖區日志記錄由一個固定大小的內存緩沖區構成,進程使用這個內存緩沖區進行日志記錄。顧名思義,該緩沖區采用循環的方式進行實現。當該緩沖區填滿了數據時,無需為新的數據分配更多的內存,而是從緩沖區開始的位置對其進行寫操作,因此將覆蓋以前的內容。請參見圖 1 中的示例。


圖 1. 對循環緩沖區進行寫操作
對循環緩沖區進行寫操作

圖 1 顯示了將兩個條目寫入到循環緩沖區后該緩沖區的狀態。在寫入了第一個日志條目(用藍色表示)之后,當該進程嘗試寫入第二個條目(用紅色表示)時,該緩沖區中已經沒有足夠的剩余空間。該進程寫入數據,一直到達緩沖區的末尾,然后將剩余的數據復制到緩沖區的開始位置,覆蓋以前的日志條目。

請參見參考資料中提供的循環緩沖區實現的示例。
通過保存一個讀指針,可以實現對循環緩沖區的讀操作;相應地移動讀指針和寫指針,以確保在進行讀操作期間,讀指針不會越過寫指針。為了提高效率,一些應用程序可以將原始數據(而不是經過格式化的數據)保存到該緩沖區。在這種情況下需要一個解析器,該解析器可以根據這些內存轉儲生成有意義的日志消息。

循環緩沖區的優點

當您可以簡單地對一個文件進行寫入操作時,為什么要使用循環緩沖區呢?因為您覆蓋了循環緩沖區中以前的內容,所以在完成該操作后,您將丟失以前的數據。與傳統的文件日志記錄機制相比,循環緩沖區提供了下列優勢。
  • 速度快。與磁盤的 I/O 操作相比,內存的寫操作要快得多。僅當需要的時候才刷新數據。
  • 持續的日志記錄可能會填滿系統中的空間,從而導致其他程序也耗盡空間并且執行失敗。在這樣的情況下,您有兩種選擇,要么手動地刪除日志信息,要么實現日志輪換策略。
  • 一旦您啟用了日志記錄,無論您是否需要它,該進程都將持續地填充硬盤上的空間。
  • 有時,您僅僅需要程序崩潰之前的相關數據,而不是該進程完整的歷史數據。
  • 有一些常見的調試函數,如 printf、write 等,可能會在多線程應用程序的情況下更改一個程序的行為,使得它們難以調試。使用這些函數會導致應用程序隱藏某些平時可能表現出來的錯誤。這些函數都是可撤銷點,并且可能導致在線程環境中產生一個該程序并不期望的掛起信號。清單 1 中假定的示例(偽代碼)和下面的清單 2 更清楚地說明了這一點。

清單 1. 沒有啟用調試的代碼
                
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
/* I should not be cancelled in the below section */
var=5;
#ifdef DEBUG
 write(fd,"Value of var = 5n",17);
#endif
var=pow(var,2);

/* I can be cancelled now */
pthread_testcancel();



清單 2. 啟用了調試的代碼
                
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
/* I should not be cancelled in the below section */
var=5;
#ifdef DEBUG
write(fd,"Value of var = 5n",17);  <======== Cancel delivered here!
#endif
var=pow(var,2);

/* I can be cancelled now */
pthread_testcancel();

 

在多線程程序中使用循環緩沖區

有時,當其他傳統的日志記錄方法失敗時,可以使用循環緩沖區日志記錄。這個部分介紹了在多線程應用程序中使用循環緩沖區啟用日志記錄時需要考慮的一些重要方面。

在訪問一個公共的資源時,同步 始終是多線程程序不可缺少的部分,日志記錄也不例外。因為每個線程都試圖對全局空間進行寫操作,所以必須確保它們同步地寫入內存,否則消息就會遭到破壞。通常,每個線程在寫入緩沖區之前都持有一個鎖,在完成操作時釋放該鎖。您可以下載一個使用鎖對內存進行寫操作的循環緩沖區示例。

這種方法具有以下的缺點:如果您的應用程序中包含幾個線程,并且每個線程都在進行詳細地日志記錄,那么該進程的整體性能將會受到影響,因為這些線程將在獲得和釋放鎖上花費了大部分的時間。

通過使得每個線程將數據寫入到它自己的內存塊,就可以完全避免同步問題。當收到來自用戶的轉儲數據的請求時,每個線程獲得一個鎖,并將其轉儲到中心位置。因為僅在將數據刷新到磁盤時獲得鎖,所以性能并不會受到很大的影響。在這樣的情況下,您可能需要一個附加的程序對日志信息進行排序(按照線程 ID 或者時間戳的順序),以便對其進行分析。您還可以選擇僅在內存中寫入消息代碼,而不是完整的格式化消息,稍后使用一個外部的實用工具解析轉儲數據,將消息代碼轉換為有意義的文本。

另一種避免同步問題的方法是,分配一個很大的全局內存塊,并將其劃分為較小的槽位,其中每個槽位都可由一個線程用來進行日志記錄。每個線程只能夠讀寫它自己的槽位,而不是整個緩沖區。當每個線程第一次嘗試寫入數據時,它會嘗試尋找一個空的內存槽位,并將其標記為忙碌。當線程獲得了一個特定的槽位時,可以將跟蹤槽位使用情況的位圖中相應的位設置為 1,當該線程退出時,重新將這個位設置為 0。同時需要維護當前使用的槽位編號的全局列表,以及正在使用它的線程的線程信息。

要避免出現這樣的情況,即一個線程已經死亡,但是卻沒有將其槽位在位圖中對應的位設置為 0,您需要一個垃圾收集器線程,它遍歷全局列表,并根據線程 ID 以固定的時間間隔進行輪詢。它負責釋放槽位并修改全局列表。請參見下面的清單 3 中給出的示例。


清單 3. 垃圾收集器線程的示例偽代碼
                
void Check_and_free(List *ptr){
    int slotno,ret_val;
    LockList();
    while(ptr){
    if ( ((ret_val = pthread_kill(ptr->thread_id,0)) == ESRCH) ){
       /* Thread has died */
       slotno=ptr->slotno;
       Free_slot(ptr->thread_id);
       Mark_bitmap_free(slotno);
      }
      ptr=ptr->next;
    }
    UnlockList();
    return ;
}
    

通常線程 ID 會得到重用,因此可能會出現這樣的情況,即一個線程已經死亡,卻沒有釋放相應的槽位,并在垃圾收集器釋放該槽位之前,再次使用了這個線程 ID 并為其分配一個新的槽位。對于新的線程來說,檢查全局列表并且重用相同的槽位(如果以前的實例使用了它的話),這是非常重要的。因為垃圾收集器線程和寫入者線程可能同時嘗試修改全局列表,所以同樣也需要使用某種鎖定機制。

當用戶對進程發出轉儲循環緩沖區數據的信號時,處理該信號的線程將不允許其他的線程再更改緩沖區的內容,并將所用槽位中的內容轉儲到文件中。清單 4清單 5 顯示了對循環緩沖區寫入數據并且將其內容轉儲到文件的示例。一旦接收到了轉儲數據的信號,將使用 is_dumping 全局變量禁止其他的線程更改該緩沖區的內容。


清單 4. 對循環緩沖區槽位 “I” 進行寫操作的示例偽代碼
                
void Write_to_buffer(char *msg){
     read_atomically(&is_dumping);
     if(!is_dumping)
       memcpy(slot[i]->ptr,msg,strlen(msg));
     return;
}
 


清單 5. 轉儲循環緩沖區數據的示例偽代碼
                
void Dump_data(int fd){
     change_atomically_to_true(&is_dumping);
     for i in each_used_slot {
        write_slot_data_to_file(fd,slot[i]);
      }
     change_atomically_to_false(&is_dumping);
     return;
}
 

結束語

通過使用內存操作代替文件操作,循環緩沖區使得日志記錄的效率更高。為緩沖區選擇合適的大小以確保轉儲相關的消息,這在進行程序的事后檢查分析時是很有幫助的。對于那些不斷地進行日志記錄的程序來說,循環緩沖區是一種理想的解決方案,并且在調試的過程中,您并不需要該程序完整的歷史信息。本文介紹了在多線程程序中實現循環緩沖區的方法和一些需要注意的內容。

熱詞搜索:

上一篇:Linux系統安全之程序日志的使用概述
下一篇:Windows 到 Linux 之旅: Linux 日志

分享到: 收藏
国产一级一区二区_segui88久久综合9999_97久久夜色精品国产_欧美色网一区二区
亚洲男人天堂一区| 972aa.com艺术欧美| 欧美一区二区视频在线观看2020| 亚洲精品高清在线| 欧美亚洲一区二区在线观看| 一区二区三区不卡视频在线观看 | 欧美三级电影一区| 午夜久久久久久久久久一区二区| 欧美日本一道本在线视频| 丝袜美腿高跟呻吟高潮一区| 欧美日韩美少妇 | 精品亚洲国内自在自线福利| 久久综合色婷婷| 国产一级精品在线| 亚洲欧美偷拍卡通变态| 欧美网站一区二区| 国产麻豆91精品| 亚洲女与黑人做爰| 欧美日韩大陆一区二区| 黄一区二区三区| 1区2区3区欧美| 欧美一区二区三区免费视频| 国产成人av福利| 亚洲国产综合色| 欧美精品一区二| 波多野结衣中文字幕一区二区三区| 亚洲欧美区自拍先锋| 欧美日韩成人一区| 国产成人av一区二区三区在线| 亚洲免费观看高清完整| 日韩视频国产视频| 色婷婷激情久久| 精品一区二区三区视频在线观看| 国产精品色在线| 4438x成人网最大色成网站| 懂色av中文一区二区三区| 亚洲成av人片一区二区梦乃 | 欧美国产一区二区在线观看| 欧美三级资源在线| 国产成人免费网站| 美女久久久精品| 亚洲国产一区视频| 亚洲国产精品二十页| 日韩西西人体444www| 日本韩国欧美国产| 国产成人福利片| 精品亚洲aⅴ乱码一区二区三区| 一区二区国产盗摄色噜噜| 久久亚洲一级片| 91精品综合久久久久久| 91一区一区三区| 国产成人免费视| 久久99九九99精品| 亚洲一区二区综合| 日韩一区欧美小说| 中文幕一区二区三区久久蜜桃| 欧美一区二区三区视频免费播放| 日本道在线观看一区二区| 高清beeg欧美| 国产精品99久久久久久久女警 | 日韩国产在线观看一区| 亚洲精品亚洲人成人网在线播放| 久久久欧美精品sm网站| 日韩一区二区三区免费看| 欧美三级资源在线| 欧美三级三级三级爽爽爽| 色综合天天综合给合国产| 成人国产在线观看| 国产精品自在欧美一区| 久久99精品一区二区三区三区| 天天影视网天天综合色在线播放| 一区二区三区中文免费| 亚洲品质自拍视频| 亚洲啪啪综合av一区二区三区| 亚洲国产精品成人综合| 日本一区二区三区国色天香 | 亚洲无人区一区| 一区二区三区四区在线免费观看| 国产精品久久毛片| 国产精品麻豆视频| 中文字幕亚洲成人| 亚洲欧美激情插| 亚洲在线视频一区| 水野朝阳av一区二区三区| 天天操天天综合网| 日本伊人精品一区二区三区观看方式| 性做久久久久久免费观看| 午夜精品久久久| 久久电影网站中文字幕 | 日韩中文欧美在线| 日本在线不卡一区| 国产一区二区视频在线| 国产电影精品久久禁18| av欧美精品.com| 欧美性受xxxx黑人xyx性爽| 欧美色电影在线| 日韩精品一区二区三区四区视频| 日韩欧美国产综合一区 | 亚洲成人动漫av| 亚洲一二三四在线观看| 日本一区二区三级电影在线观看| 中文幕一区二区三区久久蜜桃| 欧美国产视频在线| 亚洲欧美日韩系列| 一区二区三区四区视频精品免费| 亚洲免费观看视频| 亚洲激情综合网| 精品一二线国产| 粉嫩av一区二区三区| av资源站一区| 欧洲视频一区二区| 欧美军同video69gay| 99国产精品国产精品久久| 欧美在线观看一区二区| 欧美日韩免费在线视频| 国产欧美一区二区在线观看| 中文字幕在线一区二区三区| 亚洲综合激情网| 青青草国产成人av片免费| 久久99国产精品久久99果冻传媒| 老司机精品视频导航| 色哟哟国产精品免费观看| 欧美一区二区三区精品| 久久久精品黄色| 亚洲欧美aⅴ...| 麻豆精品在线观看| 色先锋aa成人| 久久综合国产精品| 亚洲欧美日韩中文字幕一区二区三区| 日韩精品午夜视频| 成人性生交大片免费看中文| av中文一区二区三区| 欧美日韩不卡一区二区| 国产欧美一区二区精品久导航| 亚洲精品成人悠悠色影视| 免费在线成人网| 91欧美一区二区| 欧美激情中文字幕| 琪琪一区二区三区| 成a人片国产精品| 欧美成人a视频| 一区二区三区四区不卡视频| 奇米亚洲午夜久久精品| 91同城在线观看| 26uuu欧美| 香蕉久久夜色精品国产使用方法| 久久不见久久见免费视频7 | 中文字幕成人av| 欧美a级一区二区| 欧美羞羞免费网站| 一区二区激情小说| 成人国产一区二区三区精品| 精品毛片乱码1区2区3区| 亚洲国产日韩一级| 成人的网站免费观看| 国产欧美精品在线观看| 日韩精品一二区| 欧美私模裸体表演在线观看| 国产精品视频看| 国产米奇在线777精品观看| 久久色视频免费观看| 美国三级日本三级久久99| 欧美日韩极品在线观看一区| 中文字幕一区二区三区在线不卡| 亚洲午夜久久久久中文字幕久| 色狠狠色狠狠综合| 成人免费一区二区三区在线观看| 麻豆国产精品777777在线| 精品久久久网站| 日本欧美加勒比视频| 欧美日韩高清一区| 一区二区三区高清在线| voyeur盗摄精品| 亚洲精品国久久99热| 一本在线高清不卡dvd| 国产精品视频观看| av资源站一区| 国产精品久久一卡二卡| 99久久精品国产观看| 国产精品护士白丝一区av| 高清在线成人网| 精品处破学生在线二十三| 成人在线视频一区| 国产精品卡一卡二卡三| 91免费版pro下载短视频| 亚洲欧美一区二区三区极速播放| 欧美色网一区二区| 视频精品一区二区| 日韩一级完整毛片| 国产一区二区三区久久悠悠色av| 欧美不卡一区二区三区| 国产露脸91国语对白| 国产精品毛片a∨一区二区三区| av亚洲产国偷v产偷v自拍| 亚洲精品免费在线| 在线亚洲免费视频| 国内偷窥港台综合视频在线播放| 精品欧美一区二区久久| 国产91精品入口| 1024精品合集|