原文地址 http://rayleeya.javaeye.com/blog/696827
共两篇文章,第一篇讲述了如何在程序中输出Log信息,第二篇详细的分析了Log信息的输出机制。
下面是第一篇(转自:http://blog.163.com/binghaitao@126/blog/static/3383532520099309366435/)
1:在编译so文件的c或cpp文件之前中加入以下代码,就可以在android中的log显示日志内容
2:就可以在c或cpp中加入LOGW(str) 就可以在android中的log中显示打印的内容
3.这样写完以后,如果直接编译,就会报 __android_log_write 方法undefined.
怎么回事呢?关键是在设置编译选项上面。
在Android.mk文件里,可以指定一个LOCAL_LDLIBS的参数。如果不指定,那么编译的时候,只会引入默认的几个重要的lib,比如libc之类的。
如果要用log,那就要把 liblog给引进来。
网上很多的写法是 LOCAL_LDLIBS := -llog ,这在build static lib的时候没什么问题。如果是build shared lib,就会报个 cannot find -llog的错误。意思是找不到liblog.so这个库文件。
因此需要改成 LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog 才可以正常编译。
其中-L参数是指定了搜索lib的路径。
下面是一个android.mk的内容的例子:
下面是第二篇(转自http://blog.csdn.net/knock/archive/2010/04/21/5511255.aspx)
为了调试,必须要将log怎么打印的搞清楚,于是有了以下的分析。
我们通常在程序中插入LOGD(..),LOGE(..)之类的语句,但什么情况下可以查看这些打印消息呢?
首先,来到定义处:system/core/include/cutils/log.h,在开头就可以看到
所以程序中#include "log.h"之前要定义LOG_TAG,不然就为空.
再看LOGD的定义
跟进
继续
再跟进
__android_log_print()是位于system/core/liblog/logd_write.c内
看__android_log_write()
write_to_log定义如下
查看一下
这段的主要意思是打开/dev/log/main,/dev/log/radio,/dev/log/events三个设备都成功则将
write_to_log指向__write_to_log_kernel,否则指向__write_to_log_null。
下面就分别看看这两个
__write_to_log_null()什么也不做,表示丢弃log信息。__write_to_log_kernel会调用log_writev()
将log写进对应的设备(/dev/log/*).
为什么写进init.rc里由init来执行的程序不能输出log呢?下面再来探究一番。。
system/core/init/init.c中,
而这两个函数为:
zap_stdio()比较狠,直接将STDIN,STDOUT,STDERR都干掉了,而open_console()则只是在/dev/console
不存在的情况下才干掉STDIN,STDOUT,STDERR,如果/dev/console存在,则将所有输入输出重定向到它
。
调用哪个取决于needs_console,
needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;
而svc->flags关于SVC_CONSOLE的部分来自于system/core/init/parser.c
这也就是说如果init.rc中service部分有请求console,则可以打印到console。
但怎么样才能打印到系统的log中,可以使用logcat来查看呢?这就需要用到logwrapper。
system/core/logwrapper/logwrapper.c中,logwrapper先打开/dev/ptmx,查询到设备名后
fork()一个子进程并将STDOUT,STDERR定向到查询到的设备。
然后开始执行要运行的程序
总结:
系统中的程序中输出log一般是到/dev/log/下的三个设备中,可以用logcat查看。
对于init运行的程序则有两种方法查看到log信息:
1.添加/system/bin/logwrapper,可以用logcat查看, 例 如
2.添加console,像sh一样直接输出到console