这几天和华为的leader面试了下。感觉不错。关键是小女。不容易。是技术面啊。我说的不容易不是面试不容易,是说在华为写代码的小女不容易。哥走南闯北这么多年,女人代码写的好真不多。

其实在任何时候,只要一面试都感觉自己会的少。都这样。那只能不断的增强能力。开始重点转入native code的学习。今天和大家聊聊log机制,这个东西也不容易。今天只谈谈log如何被写到驱动里,

有人说这个比较容易,要打log,在java里直接Log.d Log.i Log.e就可以了。嗯,不错,那问题来了。

1 java是如何把数据写到了设备里呢?
2 如何在native程序中打log呢?

自古华山一条路,看code吧。

public static int d(String tag, String msg) {
return println_native(LOG_ID_MAIN, DEBUG, tag, msg);
}
不看不知道,一看吓一跳,原来这些数据通过j//marvell 臧春杰ni直接写到了设备里了。看看jni是如何写入的把

static jint android_util_Log_println_native(JNIEnv* env, jobject clazz,
jint bufID, jint priority, jstring tagObj, jstring msgObj)
{
const char* tag = NULL;
const char* msg = NULL;

if (msgObj == NULL) {
jniThrowNullPointerException(env, "println needs a message");
return -1;
}

if (bufID < 0 || bufID >= //marvell 臧春杰LOG_ID_MAX) {
jniThrowNullPointerException(env, "bad bufID");
return -1;
}

if (tagObj != NULL)
tag = env->GetStringUTFChars(tagObj, NULL);
msg = env->GetStringUTFChars(msgObj, NULL);

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

if (tag != NULL)
env->ReleaseStringUTFChars(tagObj, tag);
env->ReleaseStringUTFChars(msgObj, msg);

return res;
}
这就比较清楚了,清楚了参数的含义。数据写到了哪个设备里?
crw-rw-rw- root log 10, 36 1970-01-01 16:42 events
crw------- root log 10, 33 1970-01-01 16:42 kernel
crw-rw-rw- root log 10, 37 1970-01-01 16:42 main
crw-rw-rw- root log 10, 35 1970-01-01 16:42 radio
crw-rw-rw- root log 10, 34 1970-01-01 16:42 system

优先级怎么样的, 消息的tag是什么? 写了什么数据。 到这里我们日然没看到写设备节点啊。不管怎么说, jni通过getStringUTFChars获取了java层的字符串。
int __android_log_buf_write(int bu//marvell 臧春杰fID, int prio, const char *tag, const char *msg)
{
struct iovec vec[3];
char tmp_tag[32];

if (!tag)
tag = "";

/* XXX: This needs to go! */
if ((bufID != LOG_ID_RADIO) &&
(!strcmp(tag, "HTC_RIL") ||
!strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
!strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
!strcmp(tag, "AT") ||
!strcmp(tag, "GSM") ||
!strcmp(tag, "STK") ||
!strcmp(tag, "CDMA") ||
//marvell 臧春杰
!strcmp(tag, "PHONE") ||
!strcmp(tag, "SMS"))) {
bufID = LOG_ID_RADIO;
/* Inform third party apps/ril/radio.. to use Rlog or RLOG */
snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
tag = tmp_tag;
}

if (prio == ANDROID_LOG_FATAL) {
android_set_abort_message(msg);
}

vec[0].iov_base = (unsigned char *) &prio;
vec[0].iov_len = 1;
vec[1].iov_base = (void *) tag;
vec[1].iov_len = strlen(tag) + 1;
vec[2].iov_base = (void *) msg;
vec[2].iov_len = strlen(msg) + 1;

return write_to_log(bufID, vec, 3);
}

这里把所有的信息放到了结构体数组里,为什么要放到结构体I数组呢? 我还不清楚。 这里对bufferid和tag做了校验,Log类会把所有的信息都写到了/dev/main设备里。这里把有些tag的信息写到了/dev/radio设备中,也就是modem信息

static int __write_to_log_init(log_id_t, struct //marvell 臧春杰 iovec *vec, size_t nr);
static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
根据这里,看到这是个函数指针,

static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
{
pthread_mutex_lock(&log_init_lock);

if (write_to_log == __write_to_log_init) {
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);

write_to_log = __write_to_log_kernel;

if (log_fds[LOG_ID_MAIN] < 0 || log_fds[LOG_ID_RADIO] < 0 ||
log_fds[LOG_ID_EVENTS] < 0) {
log_close(log_fds[LOG_ID_MAIN]);
log_close(log_fds[LOG_ID_RADIO]);
log_close(log_fds[LOG_ID_EVENTS]);
//marvell 臧春杰
log_fds[LOG_ID_MAIN] = -1;
log_fds[LOG_ID_RADIO] = -1;
log_fds[LOG_ID_EVENTS] = -1;
write_to_log = __write_to_log_null;
}

if (log_fds[LOG_ID_SYSTEM] < 0) {
log_fds[LOG_ID_SYSTEM] = log_fds[LOG_ID_MAIN];
}
}

pthread_mutex_unlock(&log_init_lock);

return write_to_log(log_id, vec, nr);
}

这里google玩个小技巧,write_to_log = __write_to_log_init, 初始化以后改成了write_to_log = __write_to_log_kernel;
这里开才是写设备节点。这样,最后

int writev( int fd, const struct iovec* vecs, int count ) //cjzang
{
int total = 0;

for ( ; count > 0; count--, vecs++ ) {
const char* buf = vecs->iov_base;
int len = vecs->iov_len;

while (len > 0) {
int ret = write( fd, buf, len ); //marvell 臧春杰
if (ret < 0) {
if (total == 0)
total = -1;
goto Exit;
}
if (ret == 0)
goto Exit;

total += ret;
buf += ret;
len -= ret;
}
}
Exit:
return total;
}
就这样,浪洼地写进去了。啪啪啪的写进去了。写到驱动里了。

那native code是如何加log呢? 他有时如何写进的呢?

native要打印log需要做一下几件事情,
1 包含头文件,那问题来了,我该包含哪个头文件呢? android 那么大,那么多头文件,要人老命,腰疼。需要包含system/core/include/log/log.h这个头文件。
#include <log/log.h> 同时需要在文件中定义log_tag
然后再需要的地方加上
ALOGD("===========================");
然后需要在makefile中加上#LOCAL_SHARED_LIBRARIES := liblog
就可以了,其实看看里面的实现,也是进入了

int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...)
{
va_list ap;
char buf[LOG_BUF_SIZE];

va_start(ap, fmt);
vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
va_end(ap);

return __android_log_buf_write(bufID, prio, tag, buf);
}

就这样,log信息就响应的写到了具体I的设备节点了。

不好整,整不好。

android log写入机制的更多相关文章

  1. Android将Log写入文件

    为什么要将Log写入文件 运行应用程序的时候,大多数是不会连接着IDE的: 而当应用程序崩溃时,我们需要收集复现步骤,在设备上复现,并进行Debug: 而由于Android手机的多样性,有些问题是某个 ...

  2. 谈谈MySQL bin log的写入机制、以及线上的参数是如何配置的

    目录 一.binlog 的高速缓存 二.刷盘机制 三.推荐的策略 推荐阅读 问个问题吧!为什么你需要了解binlog的落盘机制呢? 我来回答一下: ​ 上一篇文章提到了生产环境中你可以使用binlog ...

  3. android log机制——输出log【转】

    转自:http://blog.csdn.net/tdstds/article/details/19084327 目录(?)[-] 在android Java code中输出log Logprintln ...

  4. Android记录程序崩溃Log写入文件

    将导致程序崩溃的堆栈调用Log写入文件,便于收集bug.在调试安卓程序,由于某些原因调试时手机不能连接PC端,无法通过IDE查看程序崩溃的Log,希望log能够写入文件中,对于已经发布的App可以通过 ...

  5. Android系统Surface机制的SurfaceFlinger服务对帧缓冲区(Frame Buffer)的管理分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8046659 在前文中,我们分析了Surface ...

  6. Android包管理机制(二)PackageInstaller安装APK

    前言 在本系列上一篇文章Android包管理机制(一)PackageInstaller的初始化中我们学习了PackageInstaller是如何初始化的,这一篇文章我们接着学习PackageInsta ...

  7. Android 基础 十一 Android的消息机制

    Handler是Android消息机制的上层接口,这使得在开发应用过程中我们只需要和Handler交互即可.Handler的使用过程很简单,通过它可以轻松地将一个任务切换到Handler所在的线程中去 ...

  8. 聊一聊Android的消息机制

    聊一聊Android的消息机制 侯 亮 1概述 在Android平台上,主要用到两种通信机制,即Binder机制和消息机制,前者用于跨进程通信,后者用于进程内部通信. 从技术实现上来说,消息机制还是比 ...

  9. Android的logger机制分析

    分析安卓的Logger机制 一.概述 Logger机制是在Android系统中提供的一个轻量级的日志系统,这个日志系统是以驱动程序的形式在内核空间实现的,在用户空间分别提供了Java接口和C/C++接 ...

随机推荐

  1. docker的一些常用命令整理

    docker清除命令: 杀掉所有容器:docker kill $(docker ps -q) ; 清除所有容器:docker rm $(docker ps -a -q) ; 清除所有镜像:docker ...

  2. Intersecting Lines POJ 1269

    题目大意:给出两条直线,每个直线上的两点,求这两条直线的位置关系:共线,平行,或相交,相交输出交点. 题目思路:主要在于求交点 F0(X)=a0x+b0y+c0==0; F1(X)=a1x+b1y+c ...

  3. 第三方 XListview 上拉加载、下拉刷新、分页加载和Gson解析

    注意:此Demo用的是第三方的Xlistview.jar,需要复制me文件夹到项目中,两个XML布局文件和一张图片 把下面的复制到String中 <string name="xlist ...

  4. 初探JavaScript魅力(三)

    复选框的全选.反选和不选 <title>无标题文档</title> <style> body{background:#666;} </style> &l ...

  5. synchronized关键字以及实例锁 类锁

    Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchronized(this ...

  6. Linux学习 -- 备份与恢复

    备份 Linux系统需要备份的数据 /root/ /home/ /var/spool/mail /etc/ others 备份策略 完全备份 增量备份 差异备份 备份和恢复命令 dump  resto ...

  7. HBase伪分布安装

    1把hbase-0.94.2-security.tar.gz复制到/usr/local 2 解压缩.重命名.设置环境变量 cd /usr/local tar -zxvf hbase--security ...

  8. Cisco 学会使用Telnet、SSH

    实验目的:通过控制R1 后 , TELNET 到R2(12.1.1.2),R3(13.1.1.3)对R2,R3 进行远程管理. 在R1 上配置: R1#telnet 12.1.1.2 //从R1 TE ...

  9. 为什么MVC不是一种设计模式? ---比较Backbone和Ext4.x在MVC实现上的差异

    为什么MVC不是一种设计模式? ---比较Backbone和Ext4.x在MVC实现上的差异 大漠穷秋 前言 圣人云:不想做妈咪的小姐不是好码农. 每一个码农的心中都有一个终极理想,那就是有一天不用再 ...

  10. (转)MATLAB入门教程

    MATLAB入门教程   1.MATLAB的基本知识 1-1.基本运算与函数    在MATLAB下进行基本数学运算,只需将运算式直接打入提示号(>>)之後,并按入Enter键即可.例如: ...