Android Logcat輸出為何能自動換行輸出的原因以及多\n的作用
1. Android Logcat的是建立在Android的日誌系統之上的,日誌系統包括核心驅動模組Logger(drivers/staging/android)和liblog.so(原始碼位於/system/core/liblog下),liblog.so主要提供日誌資料的寫入與讀取介面,向下負責操作底層log驅動,向上一是提供ALOG功能給Native C與java提供log寫入,另一方面是提供給Logcat模組將日誌系統中的日誌資料讀取出來並輸出到當前系統的STDOUT。
2 adb logcat本質只是從日誌系統中迴圈讀取資料,所以也負責將日誌資料回顯到系統的標準輸出中去。
當我們在java層使用一條Log.v()或者在Native層使用ALOGD()時,日誌系統會將當前的message資料記錄
當我們adb logcat(本質只是/bin/adbd程序服務間接幫助執行了logcat),其本質就是個可執行檔案,當logcat執行時,他會預設去讀取日誌系統中的message資料,也是藉助liblog.so來讀取日誌檔案,當一個message被讀取到時,在回顯到標準輸出前,他會做一個幾個和換行符\n相關的加工處理:
a.向message一行輸出中自動新增prefix和suffix
01-08 17:28:48.731 884 1078 I vol.EventswriteEvent active_stream_changed UNKNOWN_STREAM_-1
01-08 17:28:48.733 884 1523 D OpenGLRendererdrawRenderNode
這裡的prefix如上01-08 17:28:48.733 884 1523 D 為值,從程式碼中體現如下:
logcat.cpp:main->processBuffer->android_log_printLogLine->android_log_formatLogLine:
strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);
case FORMAT_THREADTIME:
prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
"%s.%03ld %5d %5d %c %-8s: ", timeBuf, entry->tv_nsec / 1000000,
entry->pid, entry->tid, priChar, entry->tag);
strcpy(suffixBuf, "\n");
suffixLen = 1;
break;
這裡可以明顯看到prefix產生的原因,分別是日誌寫入時的時間格式還有程序和執行緒號;對suffix處理時預設是加入一個\n符,這也就解釋了為何一行日誌message包裹\n還能具備換行輸出的原因(STDOUT標準輸出在printf時每遇到一個\n就會自動換行,具體由核心驅動實現,使用者只需加入\n符號即可)。
b:判斷message的字串中是否包含/n,如果是的話,認為/n後續的字元是需要另起一行並新增對應的Prefix和suffix,即要當中兩條message來處理:
while(pm < (entry->message + entry->messageLen)) {
const char *lineStart;
size_t lineLen;
lineStart = pm;
// Find the next end-of-line in message
while (pm < (entry->message + entry->messageLen)
&& *pm != '\n') pm++;
lineLen = pm - lineStart;
strcat(p, prefixBuf);
p += prefixLen;
strncat(p, lineStart, lineLen);
p += lineLen;
strcat(p, suffixBuf);
p += suffixLen;
if (*pm == '\n') pm++;
}
}
上述程式碼是將message中的buf單個讀取後,遇到\n前的所有字元會被新增prefix和suffix,即message中的一個\n是輸出一行帶有prefix和suffix的資料快取欄位:。列入ALOGD("hello\n\nworld\n\n");
01-08 17:28:48.733 884 1523 D TAG : hello
01-08 17:28:48.733 884 1523 D TAG :
01-08 17:28:48.733 884 1523 D TAG : world
01-08 17:28:48.733 884 1523 D TAG :
01-08 17:28:48.733 884 1523 D TAG : xxx
出現的前4行行資料意味著有4個\n的存在
預設行尾不存在\n時會自動加入\n符號,末尾只存在一個\n時只會解析為一行輸出並加入\n,ALOGD中寫入的\n只作為一個數據的標誌符。
總結,每個\n用來表示接下去將會換行開始輸出ALOG中的字元日誌資料(當新的一行沒有日誌資料時,只會顯示prefix相關的內容),當一行日誌輸出到末尾時,無論末尾有無\n都會進行一次自動換行,目的是表示當前ALOD結束接下去要開始啟動輸出下一個全新的ALOG中所定義的日誌資料。