您的位置:首页 > 其它

在Logcat中增加kernel打印

2016-04-22 12:42 357 查看
http://blog.csdn.net/skdev/article/details/45026241


在Logcat中增加kernel打印


1 Logcat 的原理简介

Logcat的打印类型有events、radio、system、main等几项,执行命令如下:

Logcat –b events/radio/system/main

其原理主要是打开/dev/log/events,/dev/log/radio, /dev/log/system, /dev/log/main等设备文件,读取该文件的数据,再对数据进行解析后打印出来。


2 logcat 设备文件的存储格式

设备文件里的打印是按如下格式存储的:

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函数里获得,以达到与内核打印一致。


3本文功能实现的思路

将printk中的字符串,按logcat所需的格式存储到/dev/log/kernel设备文件里,然后就可以通过logcat
–b kernel将内核信息打印出来。


4本文功能的好处

可通过adb logcat 将内核进行实时同步打印,改善dmesg命令不能实现实时打印缺陷。


5 本文功能的实现

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: