本来准备采用写/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最终会调用到底层的方法
查看writev的定义
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 on 137 * which use standard Android logging. 138 */139return 0; 140 } 141142/* 143 * struct { 144 * // what we provide to socket 145 * android_log_header_t header; 146 * // caller provides 147 * union { 148 * struct { 149 * char prio; 150 * char payload[]; 151 * } string; 152 * struct { 153 * uint32_t tag 154 * 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 }
本质上还是调用的系统write方法,向logd进行写操作
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操作进行写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最终会调用到底层的方法
查看writev的定义
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 on 137 * which use standard Android logging. 138 */139return 0; 140 } 141142/* 143 * struct { 144 * // what we provide to socket 145 * android_log_header_t header; 146 * // caller provides 147 * union { 148 * struct { 149 * char prio; 150 * char payload[]; 151 * } string; 152 * struct { 153 * uint32_t tag 154 * 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 }
本质上还是调用的系统write方法,向logd进行写操作
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操作进行写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
基于Android N的Log机制浅析
本来准备采用写/dev/log/main的方式进行底层的写log测试,但是Android6后就没有/dev/log/main了,根据参考资料来查看
Log.d以及Slog的写log最终会调用到底层的方法
查看writev的定义
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 on 137 * which use standard Android logging. 138 */139return 0; 140 } 141142/* 143 * struct { 144 * // what we provide to socket 145 * android_log_header_t header; 146 * // caller provides 147 * union { 148 * struct { 149 * char prio; 150 * char payload[]; 151 * } string; 152 * struct { 153 * uint32_t tag 154 * 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 }
本质上还是调用的系统write方法,向logd进行写操作
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操作进行写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