Logcat的打印类型有events、radio、system、main等几项,执行命令如下:
Logcat –b events/radio/system/main
其原理主要是打开/dev/log/events,/dev/log/radio, /dev/log/system, /dev/log/main等设备文件,读取该文件的数据,再对数据进行解析后打印出来。
设备文件里的打印是按如下格式存储的:
prioTAG’\0’msg’\0’
prio 是一个整型,值为0~8,对应的优化级别如下:
typedef enum android_LogPriority {
ANDROID_LOG_UNKNOWN = 0,
ANDROID_LOG_DEFAULT, /* onlyfor SetMinPriority() */
ANDROID_LOG_VERBOSE,
ANDROID_LOG_DEBUG,
ANDROID_LOG_INFO,
ANDROID_LOG_WARN,
ANDROID_LOG_ERROR,
ANDROID_LOG_FATAL,
ANDROID_LOG_SILENT, /* onlyfor SetMinPriority(); must be last */
} android_LogPriority;
TAG是一个标签,字符串类型,在本文中定义为“KERNEL”,以表示内核打印。
Msg 是打印的字符串,本文中该字符串由printk函数里获得,以达到与内核打印一致。
将printk中的字符串,按logcat所需的格式存储到/dev/log/kernel设备文件里,然后就可以通过logcat –b kernel将内核信息打印出来。
可通过adb logcat 将内核进行实时同步打印,改善dmesg命令不能实现实时打印缺陷。
Index: drivers/staging/android/logger.c
===================================================================
--- drivers/staging/android/logger.c (版本 13)
+++ drivers/staging/android/logger.c (工作副本)
@@ -316,6 +316,7 @@
return count;
}
+
/*
*logger_aio_write - our write method, implementing support for write(),
*writev(), and aio_write(). Writes are our fast path, and we try to optimize
@@ -372,7 +373,6 @@
iov++;
ret += nr;
}
-
mutex_unlock(&log->mutex);
/* wake up any blocked readers */
@@ -559,6 +559,7 @@
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)
+DEFINE_LOGGER_DEVICE(log_kernel,LOGGER_LOG_KERNEL, 256*1024)
static struct logger_log *get_log_from_minor(intminor)
{
@@ -570,9 +571,73 @@
return &log_radio;
if (log_system.misc.minor == minor)
return &log_system;
+ if (log_kernel.misc.minor == minor)
+ return &log_kernel;
return NULL;
}
+ssize_t logger_write_ext(const char *buf,unsigned long count)
+{
+ struct logger_log *log = &log_kernel;
+ size_t orig = log->w_off;
+ struct logger_entry header;
+ struct timespec now;
+ ssize_t nr = 0;
+ int prio = 3;
+ char tag[7] = {'K','E','R','N','E','L','\0'};
+
+ now = current_kernel_time();
+
+ header.pid = current->tgid;
+ header.tid = current->pid;
+ header.sec = now.tv_sec;
+ header.nsec = now.tv_nsec;
+ header.len = min_t(size_t, count+8, LOGGER_ENTRY_MAX_PAYLOAD);
+
+ /* null writes succeed, return zero */
+ if (count == 0)
+ return 0;
+
+ mutex_lock(&log->mutex);
+
+ /*
+ * Fix up any readers, pulling them forward to the first readable
+ * entry after (what will be) the new write offset. We do this now
+ * because if we partially fail, we can end up with clobbered log
+ * entries that encroach on readable buffer.
+ */
+ fix_up_readers(log, sizeof(struct logger_entry) + header.len);
+
+ do_write_log(log, &header, sizeof(struct logger_entry));
+
+ nr = do_write_log_from_user(log, &prio, 1);
+ if (unlikely(nr < 0)) {
+ log->w_off = orig;
+ mutex_unlock(&log->mutex);
+ return nr;
+ }
+
+ nr = do_write_log_from_user(log, tag, 7);
+ if (unlikely(nr < 0)) {
+ log->w_off = orig;
+ mutex_unlock(&log->mutex);
+ return nr;
+ }
+
+ nr = do_write_log_from_user(log, buf, count);
+ if (unlikely(nr < 0)) {
+ log->w_off = orig;
+ mutex_unlock(&log->mutex);
+ return nr;
+ }
+
+ mutex_unlock(&log->mutex);
+
+ /* wake up any blocked readers */
+ wake_up_interruptible(&log->wq);
+
+ return nr;
+}
static int __init init_log(struct logger_log*log)
{
int ret;
@@ -610,6 +675,10 @@
if (unlikely(ret))
goto out;
+ ret = init_log(&log_kernel);
+ if (unlikely(ret))
+ goto out;
+
out:
return ret;
}
Index: drivers/staging/android/logger.h
===================================================================
--- drivers/staging/android/logger.h (版本 13)
+++ drivers/staging/android/logger.h (工作副本)
@@ -34,6 +34,7 @@
#define LOGGER_LOG_EVENTS "log_events" /* system/hardware events */
#define LOGGER_LOG_SYSTEM "log_system" /* system/framework messages */
#define LOGGER_LOG_MAIN "log_main" /* everything else */
+#define LOGGER_LOG_KERNEL "log_kernel" /* kernel */
#define LOGGER_ENTRY_MAX_LEN (4*1024)
#define LOGGER_ENTRY_MAX_PAYLOAD \
Index: kernel/printk.c
===================================================================
--- kernel/printk.c (版本 13)
+++ kernel/printk.c (工作副本)
@@ -784,11 +784,15 @@
*See the vsnprintf() documentation for format string extensions over C99.
*/
+extern ssize_t logger_write_ext(const char*buf, unsigned long count);
+
asmlinkage int printk(const char *fmt, ...)
{
va_list args;
int r;
-
+ char trace_buf[1024];
+ int len = 0;
+
#ifdef CONFIG_KGDB_KDB
if (unlikely(kdb_trap_printk)) {
va_start(args, fmt);
@@ -800,7 +804,9 @@
va_start(args, fmt);
r = vprintk(fmt, args);
va_end(args);
-
+
+ len = vsnprintf(trace_buf, 1024, fmt, args);
+ logger_write_ext(trace_buf,len+1);
return r;
}