这几天和华为的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. shell 入门教程

    打开文本编辑器,新建一个文件,扩展名为sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好.     一  惯例,第一个shell #!/bin/bash echo "Hello ...

  2. github  安装配置以及使用遇到的一些问题

    Git是一个分布式的版本控制系统,最初由Linus Torvalds编写,用作Linux内核代码的管理.在推出后,Git在其它项目中也取得了很大成功,尤其是在Ruby社区中.目前,包括Rubinius ...

  3. Video Cards

    Video Cards time limit per test 1 second memory limit per test 256 megabytes input standard input ou ...

  4. 运行第一个SparkKPI程序

    1.复制一个examples中SparkPi.scala到IntelliJ IDEA编辑器,运行,出现错误: “org.apache.spark.SparkException: A master UR ...

  5. Chapter 1 First Sight——13

    It was just drizzling still, not enough to soak me through immediately as I reached for the house ke ...

  6. If only it could be all the same like we first me

    为什么 你当时对我好 Why? You nice to me at that time. 又为什么 现在变得冷淡了 Why? Now you give a cold shoulder to me. 我 ...

  7. Zabbix之配置文件详解

    zabbix的配置文件一般有三种:zabbixserver的配置文件zabbix_server.confzabbixproxy的配置文件zabbix_proxy.confzabbix_agentd的配 ...

  8. 4-20ma电流信号转0-5v()

    源:4-20ma电流信号转0-5v 电压转电流电路原理图(0-5V转4-20mA) 4mA-20mA转0-5v电路问题,LM324一直输出10V

  9. Android -----paint cap join 理解 ,paint画笔形状设置

    引自:http://www.2cto.com/kf/201501/370215.html 网上查了很多资料,对paint的里面的枚举类cap join讲的不是很透彻.在这里自己做一个比较深入的研究. ...

  10. 【转】CentOS安装PF_RING(虚拟机)

    1.       概述 PF_RING是Luca Deri发明的提高内核处理数据包效率,并兼顾应用程序的补丁,如Libpcap和TCPDUMP等,以及一些辅助性程序(如ntop查看并分析网络流量等). ...