muduo 日誌庫學習 一

2021-09-12 19:22:31 字數 3262 閱讀 3785

大佬部落格

muduo的日誌庫由logstream、logging、logfile、asynclogging組成。這裡主要說明一下,這些檔案(主要是檔案裡面對應的類)之間是怎麼關聯,並協同工作的。

logstream類裡面有乙個buffer成員(乙個模板類,並非muduo::buffer類)。該類主要負責將要記錄的日誌內容放到這個buffer裡面。包括字串,整型、double型別(整型和double要先將之轉換成字元型,再放到buffer裡面)。該類對這些型別都過載了《操作符。這個logstream類不做具體的io操作。以後要是需要這個buffer裡的資料,可以呼叫logstream的buffer()函式,這個函式返回const buffer&

logging.**件定義了logger類,而非logging類。 logger類用列舉型別定義了日誌等級。

enum loglevel

在logging.**件中,還定義了一系列的巨集定義。

#define log_trace if (muduo::logger::loglevel() <= muduo::logger::trace) \

muduo::logger(__file__, __line__, muduo::logger::trace, __func__).stream()

#define log_debug if (muduo::logger::loglevel() <= muduo::logger::debug) \

muduo::logger(__file__, __line__, muduo::logger::debug, __func__).stream()

#define log_info if (muduo::logger::loglevel() <= muduo::logger::info) \

muduo::logger(__file__, __line__).stream()

#define log_warn muduo::logger(__file__, __line__, muduo::logger::warn).stream()

#define log_error muduo::logger(__file__, __line__, muduo::logger::error).stream()

#define log_fatal muduo::logger(__file__, __line__, muduo::logger::fatal).stream()

#define log_syserr muduo::logger(__file__, __line__, false).stream()

#define log_sysfatal muduo::logger(__file__, __line__, true).stream()

我們使用日誌功能就是通過這些巨集的。比如

muduo::logger(__file__,__line__,muduo::logger::trace,__func__).stream()<<"the server has read the client message";
而logger類返回的stream是乙個logstream物件,於是通過這些巨集進行的日誌記錄將存放到logstream物件中的乙個buffer裡面。前面已經說到logstream函式並不進行實際的io操作,所以寫入logstream的資料通過buffer()函式獲取。

logger類還定義了兩個函式指標,用於設定日誌的輸出位置。因為這種設定是基於類的,而不是基於物件,所以自然其有兩個靜態變數g_output,g_flush分別存放 輸出函式和 重新整理函式。

typedef void (*outputfunc)(const char* msg, int len);

typedef void (*flushfunc)();

預設情況下,其是向stdout(即標準輸出)進行輸出的。

void defaultoutput(const char* msg, int len)

void defaultflush()

logger::outputfunc g_output = defaultoutput;

logger::flushfunc g_flush = defaultflush;

此外,這個類還提供了兩個靜態函式,用於設定靜態變數g_output和g_flush的。

static void setoutput(outputfunc);

static void setflush(flushfunc);

不用說就能感覺到 這兩個函式很有用,因為其可以修改輸出函式,進而重定向日誌輸出,我們可以將之修改為自己寫的輸出函式,在這個輸出函式中,可以向我們想要輸出的快取或者檔案進行輸出。在muduo中,一般是將日誌重定向到asynclogging物件中,具體是:先存放到asynclogging物件的乙個快取中,然後由asynclogging進行非同步寫入檔案中。

logger類還有乙個特徵就是其使用了impl方法,定義了乙個私有的impl類。這個impl類有乙個logstream類。同大多數impl方法一樣,logger類的具體操作由這個impl類來完成。不過,logger類中的impl成員不是乙個指標。使用impl方法的一大原因是為了閉源,不僅僅隱藏實現**還隱藏類的私有成員函式。但對於muduo這個開源庫來說,這沒有意義。而且使用指標的話,new的時候需要在堆中申請空間,這無疑會降低執行速度。

logger類是間接進行io的。logger的析構函式如下:

logger::~logger()

}

在析構函式中,會呼叫輸出函式g_output,把日誌資料(已經存放於buf中)輸出。

現在來說一下logger類和logstream類是怎麼配合工作的。

使用log_*之類的巨集會建立乙個臨時匿名logger物件,這個物件有乙個impl物件,而impl物件有乙個logstream物件。log_*巨集會返回乙個logstream物件的引用。用於將內容輸入到logstream中的乙個buffer中。在logger的析構函式中,將存於logstream的buffer的日誌內容輸出。

log_*的巨集,建立乙個臨時匿名logger物件,臨時匿名很重要,因為臨時匿名物件是一使用完就馬上銷毀,呼叫析構函式。而c++對於棧中的具名物件,先建立的後銷毀。這就使得後建立的logger物件先於先建立的logger物件銷毀。即先呼叫析構函式將日誌輸出,這就會使得日誌內容反序(具體說是乙個由{}包括的塊中反序)。使用臨時匿名logger物件的效果就是:log_*這行**不僅僅包含日誌內容,還會馬上把日誌輸出。

muduo 日誌庫學習 二

logfile類和asynclogging類各有自己的buffer 在下文中,分別記為file buffer和async buffer 當使用者使用log 寫入日誌內容時,將會把日誌內容寫入到async buffer中,當async buffer寫滿了,就會把async buffer中的內容寫入到f...

學習一下muduo網路庫(一)

我是跟著陳碩大神的 linux多執行緒服務端程式設計 使用muduo c 網路庫 書學習muduo的。書看了不到1 3,一直對著書和 學習,還是有些累的,而且根據我以往的經驗,我看書看完後,一般就不去管它了,久而久之,我就忘記了我看過 學過的內容了 我一直都覺得我的記憶力只有7天 因此我打算寫寫自己...

muduo庫學習篇 Thread類學習

多執行緒程式設計在任何語言中基本都是乙個繞不開的話題,如果我們想要發揮計算機多核的優勢,提高程式的響應速度,就一定要使用到多執行緒程式設計技術。因此muduo庫一定少不了thread的封裝,接下來我們開始學習muduo庫thread類的封裝。如果讓我自己設計乙個thread類的話我能想到的有哪些 上...