<자바클래스 android.util.Log> Log 클래스안에 구현된 메소드는 v(), d(), i(), w(), e() 등이 있다. 각각은 VERVOSE, DEBUG, INFO, WARN, ERROR 를 나타낸다. 이는 vervosity(자세함? 장황함)의 순서이다. Verbose 는 개발하는 동안에만 컴파일되고, Debug 는 컴파일되지만, runtime 시에 strip 된다. Error / warning / info 는 항상 동작한다. 보통은 본인이 작성하는 클래스에 TAG 라는 상수를 선언하는 것이 좋다. 왜냐면 Log 클래스의 메소드들의 첫번째 파라미터가 tag 를 나타내는 String 타입이기 때문에, 보통 Log 함수를 호출할 경우에 TAG 를 선언한 후에 Log.v(TAG, "statements") 와 같이 사용한다. Log.v() 함수의 구현부를 살펴보자. public static int v(String tag, String msg) { public static native int println_native(int bufID, int priority, String tag, String msg); 위 코드에서 보다시피 Log.v() 함수는 native 함수인 println_native 함수를 호출하도록 되어있다. println_native() 함수는 frameworks/base/core/jni/android_util_Log.cpp 에 구현되어 있다. static jint android_util_Log_println_native(JNIEnv* env, jobject clazz, if (msgObj == NULL) {
npeClazz = env->FindClass("java/lang/NullPointerException"); env->ThrowNew(npeClazz, "println needs a message"); if (bufID < 0 || bufID >= LOG_ID_MAX) { npeClazz = env->FindClass("java/lang/NullPointerException"); env->ThrowNew(npeClazz, "bad bufID"); if (tagObj != NULL) int res = __android_log_buf_write(bufID, (android_LogPriority)priority, tag, msg); if (tag != NULL) return res; /* 관련부분을 뜯어보면 위 코드와 같이 구현되어 있다. 즉 println_native() 함수는 jni 의 매핑을 통해서 실제로는 android_util_Log_println_native() 함수를 호출하도록 되어있다. JNI 로 두 함수가 연결되는 내용은 다음을 참조하면 된다. (JNI 네이티브 함수에 직접 등록방법) 이에 대해서는 따로 정리할 예정이다. android_util_Log_println_native() 함수는 최종적으로 __android_log_buf_write() 함수를 호출한다. 이 함수는 system/core/liblog/logd_write.c 에 구현되어 있고, write_to_log 라는 함수 포인터를 호출하는 데, 처음에 __write_to_log_init 으로 세팅되어 있고, 결과적으로 __write_to_log_kernel 함수를 호출하게 된다. __write_to_log_kernel 은 각각 관련된 character device 에 해당 로그를 write 하게 된다. 안드로이드의 log 는 총 3가지 카테고리로 나뉘는데, GSM/CDMA/RIL/SMS 등 radio 관련된 내용(/dev/radio)과 시스템/하드웨어 관련된 내용(/dev/system), 이벤트 관련 내용(/dev/events) 등으로 나뉜다. device read/write 관련 자세한 것은 kernel/drivers/staging/android/logger.c 파일에 구현되어 있다. 각각 character device 는 초기화 시점(init_logger())에 misc device 로 등록(register_misc())하고, 각각의 file operation 은 logger_fops 로 등록한다.(DEFINE_LOGGER_DEVICE) logger_fops 는 다음과 같이 정의되었기 때문에, 해당 character device 에 write 를 하게 되면, logger_aio_write() 함수가 호출된다. static const struct file_operations logger_fops = { logger_aio_write() 는 최종적으로 do_write_log_from_user() 를 호출하고, 해당 함수는 디바이스에 해당하는 버퍼에 파라미터로 넘어온 user 영역 데이터를 write offset 부분에 기록하고, write offset 을 증가시킨다. 반대로 read 는 logger_read() 함수를 호출하고, 최종적으로 do_read_log_to_user() 를 호출한다. 해당 함수는 읽을 데이터가 없는 경우 TASK_INTERRUPTIBLE 상태로 sleep 한다. 데이터가 있는 경우 해당 버퍼에서 user 영역 메모리로 데이터를 복사해주고 read offset 을 수정해준다. 참고 : http://blog.csdn.net/fuyajun01/article/details/6787729 |