logcat探検隊 - ReDo

2013年11月25日

logcat探検隊

droidcat.jpg
「なんだかんだ言って重宝するけどさほど高度じゃない気配がするのであまり信用しない」logcatをもう少し調べてみることにしました。

logcat | Android Developer
http://developer.android.com/tools/help/logcat.html
Log | Android Developer
http://developer.android.com/reference/android/util/Log.html
・System.out.printlnでも出る
・adb logcat -v timeするとコマンドラインでも時刻が出る
・isLoggable()とかwtf()とかgetStackTraceString()とかかゆいところに手が届きそうで「そこかゆくなることあんまりなないんじゃね」みたいなメソッドがある

では、ここからはframework配下に潜ってみます。

android.util.Log.java
http://tools.oesf.biz/android-4.4.0_r1.0/xref/frameworks/base/core/java/android/util/Log.java

結局Nativeのprintln_nativeを呼んでいる

    /** @hide */ public static native int println_native(int bufID,
            int priority, String tag, String msg);

http://tools.oesf.biz/android-4.4.0_r1.0/xref/frameworks/base/core/jni/android_util_Log.cpp

int res = __android_log_buf_write(bufID, (android_LogPriority)priority, tag, msg);

http://tools.oesf.biz/android-4.4.0_r1.0/xref/system/core/liblog/logd_write.c#__android_log_buf_write

int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)

NDKはこちらっぽい。
http://tools.oesf.biz/android-2.3_r1.0/xref/system/core/liblog/logd_write.c

int __android_log_write(int prio, const char *tag, const char *msg)

初期化処理__write_to_log_initによって、FileDescriptorの分岐がされている。

static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
(中略)
        log_fds[LOG_ID_MAIN] = log_open("/dev/"LOGGER_LOG_MAIN, O_WRONLY);
        log_fds[LOG_ID_RADIO] = log_open("/dev/"LOGGER_LOG_RADIO, O_WRONLY);
        log_fds[LOG_ID_EVENTS] = log_open("/dev/"LOGGER_LOG_EVENTS, O_WRONLY);
        log_fds[LOG_ID_SYSTEM] = log_open("/dev/"LOGGER_LOG_SYSTEM, O_WRONLY);

なんか/dev/配下をopenしてるので実機で確認。

$ adb shell ls -l /dev/log
crw-rw-rw- root     log       10,  45 1970-01-20 07:42 events
crw-rw-rw- root     log       10,  46 1970-01-20 07:42 main
crw-rw-rw- root     log       10,  44 1970-01-20 07:42 radio
crw-rw-rw- root     log       10,  43 1970-01-20 07:42 system

結局キャラクタ型デバイスに吸い込まれてる様だ。多分ただのサイクリックなバッファなんだろうけど詳細が分からない。
そういえばlogcatはバッファサイズ設定があったような。それらしきキーワードでぐぐってみる。

logcatの容量を増やす
https://sites.google.com/site/hippunosource/home/android/debug_tips#TOC-logcat-1

logcatの容量は、以下の箇所で変更することができる。
kernel/common/drivers/staging/android/logger.c

Kernelのソースを見に行く。

https://android.googlesource.com/kernel/common/+/android-3.4/drivers/staging/android/logger.c

DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 256*1024)
DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 256*1024)
DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 256*1024)
DEFINE_LOGGER_DEVICE(log_system, LOGGER_LOG_SYSTEM, 256*1024)

昨今は256kがデフォルトらしい。つまりadb logcatってやるとまず256kずらーって出るわけですね。

で、このサイズですが

What is the size limit for Logcat?
http://stackoverflow.com/questions/6321555/what-is-the-size-limit-for-logcat

To see the size use -g
えっ、マジで?
$ adb shell logcat -g
/dev/log/main: ring buffer is 256Kb (255Kb consumed), max entry is 5120b, max payload is 4076b
/dev/log/system: ring buffer is 256Kb (255Kb consumed), max entry is 5120b, max payload is 4076b

マジだった。(Nexus 5 4.4調べ)

entryとかpayloadとかは1回で放り込める量、とかringぐるぐる単位、とかですかね。
logger.cが丁寧にかかれてるので真面目に読めば分かるんんだろうけど深く考えない。

・SDK(Java)なandroid.util.LogもNDKな__android_log_writeも結局同じとこに落ち着く。
・Kernel中のキャラクタドライバとして/dev/log/配下に目的別リングバッファが用意され、各プロセスからやいのやいの書きこまれる。
・adb logcat等は適当に権限もって読みだしてる。

面白かった。

コメントする