【Android】log系统初识

来源:互联网 发布:java 成功生成文件夹 编辑:程序博客网 时间:2024/06/04 23:31




本来准备采用写/dev/log/main的方式进行底层的写log测试,但是Android6后就没有/dev/log/main了,根据参考资料来查看分析,
得到一个大致的概念,Android中由于log量大,为了方便的处理log,采用进程logd来写log,我们调用Log.d()方法写log的时候,会导致底层通过socket向logd进程写数据,logd将数据写到其缓存中,当使用logcat去获取数据的时候,也是通过socket通信去获取数据。

Log.d以及Slog的写log最终会调用到底层的方法
/system/core/liblog/logd_writer.c

117staticintlogdWrite(log_id_tlogId, structtimespec *ts,118structiovec *vec, size_tnr)119{120ssize_tret;121staticconstunsignedheaderLength = 1;122structiovecnewVec[nr + headerLength];123android_log_header_theader;124size_t i, payloadSize;125staticatomic_int_fast32_tdropped;126staticatomic_int_fast32_tdroppedSecurity;127128if (logdLoggerWrite.context.sock < 0) {129return -EBADF;130 }131132/* logd, after initialization and priv drop */133if (__android_log_uid() == AID_LOGD) {134/*135 * ignore log messages we send to ourself (logd).136 * Such log messages are often generated by libraries we depend on137 * which use standard Android logging.138 */139return 0;140 }141142/*143 * struct {144 * // what we provide to socket145 * android_log_header_t header;146 * // caller provides147 * union {148 * struct {149 * char prio;150 * char payload[];151 * } string;152 * struct {153 * uint32_t tag154 * char payload[];155 * } binary;156 * };157 * };158 */159160header.tid = gettid();161header.realtime.tv_sec = ts->tv_sec;162header.realtime.tv_nsec = ts->tv_nsec;163164newVec[0].iov_base = (unsignedchar *)&header;165newVec[0].iov_len = sizeof(header);166167if (logdLoggerWrite.context.sock > 0) {168int32_tsnapshot = atomic_exchange_explicit(&droppedSecurity, 0,169memory_order_relaxed);170if (snapshot) {171android_log_event_int_tbuffer;172173header.id = LOG_ID_SECURITY;174buffer.header.tag = htole32(LIBLOG_LOG_TAG);175buffer.payload.type = EVENT_TYPE_INT;176buffer.payload.data = htole32(snapshot);177178newVec[headerLength].iov_base = &buffer;179newVec[headerLength].iov_len = sizeof(buffer);180181ret = TEMP_FAILURE_RETRY(writev(logdLoggerWrite.context.sock, newVec, 2));182if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {183atomic_fetch_add_explicit(&droppedSecurity, snapshot,184memory_order_relaxed);185 }186 }
查看writev的定义
/system/core/liblog/uio.c

52LIBLOG_ABI_PUBLICintwritev(intfd, conststructiovec *vecs, intcount)53{54inttotal = 0;5556for ( ; count > 0; count--, vecs++ ) {57constchar* buf = vecs->iov_base;58intlen = vecs->iov_len;5960while (len > 0) {61intret = write( fd, buf, len );62if (ret < 0) {63if (total == 0)64total = -1;65gotoExit;66 }67if (ret == 0)68gotoExit;6970total += ret;71buf += ret;72len -= ret;73 }74 }75Exit:76returntotal;77}78
本质上还是调用的系统write方法,向logd进行写操作
也就是说,如果给入合适的输入格式,我们是可以直接通过write操作进行写log
如:
int main(int argc, char* const argv[])
{
        int fd = open("/dev/socket/logdw", O_RDWR);
        if (fd < 0)
                aerr << "fd < 0" << endl;
        else
                aout << "fd = " << fd << endl;

        write(fd, "=====00 log write===============", 22);


}

直接这样写是有问题的,数据格式不对,
Unknown:/data/local/tmp # ./wtLog
fd < 0
这个测试需要继续研究

如果要正确的处理,需要再查看logd的处理方式进行分析
logd启动后的入口是/system/core/logd/main.cpp中的main方法

logd对log进行处理,读log是从/dev/socket/logdr来获取数据
log处理流程
Log.d() -> liblog ---socket--->logd ----socket---->logcat


参考资料

本来准备采用写/dev/log/main的方式进行底层的写log测试,但是Android6后就没有/dev/log/main了,根据参考资料来查看

Log.d以及Slog的写log最终会调用到底层的方法
/system/core/liblog/logd_writer.c

117staticintlogdWrite(log_id_tlogId, structtimespec *ts,118structiovec *vec, size_tnr)119{120ssize_tret;121staticconstunsignedheaderLength = 1;122structiovecnewVec[nr + headerLength];123android_log_header_theader;124size_t i, payloadSize;125staticatomic_int_fast32_tdropped;126staticatomic_int_fast32_tdroppedSecurity;127128if (logdLoggerWrite.context.sock < 0) {129return -EBADF;130 }131132/* logd, after initialization and priv drop */133if (__android_log_uid() == AID_LOGD) {134/*135 * ignore log messages we send to ourself (logd).136 * Such log messages are often generated by libraries we depend on137 * which use standard Android logging.138 */139return 0;140 }141142/*143 * struct {144 * // what we provide to socket145 * android_log_header_t header;146 * // caller provides147 * union {148 * struct {149 * char prio;150 * char payload[];151 * } string;152 * struct {153 * uint32_t tag154 * char payload[];155 * } binary;156 * };157 * };158 */159160header.tid = gettid();161header.realtime.tv_sec = ts->tv_sec;162header.realtime.tv_nsec = ts->tv_nsec;163164newVec[0].iov_base = (unsignedchar *)&header;165newVec[0].iov_len = sizeof(header);166167if (logdLoggerWrite.context.sock > 0) {168int32_tsnapshot = atomic_exchange_explicit(&droppedSecurity, 0,169memory_order_relaxed);170if (snapshot) {171android_log_event_int_tbuffer;172173header.id = LOG_ID_SECURITY;174buffer.header.tag = htole32(LIBLOG_LOG_TAG);175buffer.payload.type = EVENT_TYPE_INT;176buffer.payload.data = htole32(snapshot);177178newVec[headerLength].iov_base = &buffer;179newVec[headerLength].iov_len = sizeof(buffer);180181ret = TEMP_FAILURE_RETRY(writev(logdLoggerWrite.context.sock, newVec, 2));182if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {183atomic_fetch_add_explicit(&droppedSecurity, snapshot,184memory_order_relaxed);185 }186 }
查看writev的定义
/system/core/liblog/uio.c

52LIBLOG_ABI_PUBLICintwritev(intfd, conststructiovec *vecs, intcount)53{54inttotal = 0;5556for ( ; count > 0; count--, vecs++ ) {57constchar* buf = vecs->iov_base;58intlen = vecs->iov_len;5960while (len > 0) {61intret = write( fd, buf, len );62if (ret < 0) {63if (total == 0)64total = -1;65gotoExit;66 }67if (ret == 0)68gotoExit;6970total += ret;71buf += ret;72len -= ret;73 }74 }75Exit:76returntotal;77}78
本质上还是调用的系统write方法,向logd进行写操作
也就是说,如果给入合适的输入格式,我们是可以直接通过write操作进行写log
如:
int main(int argc, char* const argv[])
{
        int fd = open("/dev/socket/logdw", O_RDWR);
        if (fd < 0)
                aerr << "fd < 0" << endl;
        else
                aout << "fd = " << fd << endl;

        write(fd, "=====00 log write===============", 22);


}

直接这样写是有问题的,数据格式不对,
Unknown:/data/local/tmp # ./wtLog
fd < 0
这个测试需要继续研究

如果要正确的处理,需要再查看logd的处理方式进行分析
logd启动后的入口是/system/core/logd/main.cpp中的main方法

logd对log进行处理,读log是从/dev/socket/logdr来获取数据
log处理流程
Log.d() -> liblog ---socket--->logd ----socket---->logcat

http://blog.csdn.net/KM_Cat/article/details/61320398

基于Android N的Log机制浅析


Android6的Logger日志系统



本来准备采用写/dev/log/main的方式进行底层的写log测试,但是Android6后就没有/dev/log/main了,根据参考资料来查看

Log.d以及Slog的写log最终会调用到底层的方法
/system/core/liblog/logd_writer.c

117staticintlogdWrite(log_id_tlogId, structtimespec *ts,118structiovec *vec, size_tnr)119{120ssize_tret;121staticconstunsignedheaderLength = 1;122structiovecnewVec[nr + headerLength];123android_log_header_theader;124size_t i, payloadSize;125staticatomic_int_fast32_tdropped;126staticatomic_int_fast32_tdroppedSecurity;127128if (logdLoggerWrite.context.sock < 0) {129return -EBADF;130 }131132/* logd, after initialization and priv drop */133if (__android_log_uid() == AID_LOGD) {134/*135 * ignore log messages we send to ourself (logd).136 * Such log messages are often generated by libraries we depend on137 * which use standard Android logging.138 */139return 0;140 }141142/*143 * struct {144 * // what we provide to socket145 * android_log_header_t header;146 * // caller provides147 * union {148 * struct {149 * char prio;150 * char payload[];151 * } string;152 * struct {153 * uint32_t tag154 * char payload[];155 * } binary;156 * };157 * };158 */159160header.tid = gettid();161header.realtime.tv_sec = ts->tv_sec;162header.realtime.tv_nsec = ts->tv_nsec;163164newVec[0].iov_base = (unsignedchar *)&header;165newVec[0].iov_len = sizeof(header);166167if (logdLoggerWrite.context.sock > 0) {168int32_tsnapshot = atomic_exchange_explicit(&droppedSecurity, 0,169memory_order_relaxed);170if (snapshot) {171android_log_event_int_tbuffer;172173header.id = LOG_ID_SECURITY;174buffer.header.tag = htole32(LIBLOG_LOG_TAG);175buffer.payload.type = EVENT_TYPE_INT;176buffer.payload.data = htole32(snapshot);177178newVec[headerLength].iov_base = &buffer;179newVec[headerLength].iov_len = sizeof(buffer);180181ret = TEMP_FAILURE_RETRY(writev(logdLoggerWrite.context.sock, newVec, 2));182if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {183atomic_fetch_add_explicit(&droppedSecurity, snapshot,184memory_order_relaxed);185 }186 }
查看writev的定义
/system/core/liblog/uio.c

52LIBLOG_ABI_PUBLICintwritev(intfd, conststructiovec *vecs, intcount)53{54inttotal = 0;5556for ( ; count > 0; count--, vecs++ ) {57constchar* buf = vecs->iov_base;58intlen = vecs->iov_len;5960while (len > 0) {61intret = write( fd, buf, len );62if (ret < 0) {63if (total == 0)64total = -1;65gotoExit;66 }67if (ret == 0)68gotoExit;6970total += ret;71buf += ret;72len -= ret;73 }74 }75Exit:76returntotal;77}78
本质上还是调用的系统write方法,向logd进行写操作
也就是说,如果给入合适的输入格式,我们是可以直接通过write操作进行写log
如:
int main(int argc, char* const argv[])
{
        int fd = open("/dev/socket/logdw", O_RDWR);
        if (fd < 0)
                aerr << "fd < 0" << endl;
        else
                aout << "fd = " << fd << endl;

        write(fd, "=====00 log write===============", 22);


}

直接这样写是有问题的,数据格式不对,
Unknown:/data/local/tmp # ./wtLog
fd < 0
这个测试需要继续研究

如果要正确的处理,需要再查看logd的处理方式进行分析
logd启动后的入口是/system/core/logd/main.cpp中的main方法

logd对log进行处理,读log是从/dev/socket/logdr来获取数据
log处理流程
Log.d() -> liblog ---socket--->logd ----socket---->logcat
原创粉丝点击