首页 > 编程知识 正文

androidlog使用方法,android怎么打印log日志

时间:2023-05-06 03:23:55 阅读:275710 作者:4156

一、设置保存log文件的路径

在手机刚开机的时候,会有类似如下命令执行

/system/bin/logcat -r 5120 -v threadtime -v usec -v printable -n 5 -f /data/local/log/logcat.log



/system/bin/logcat -r 5120 -v threadtime -v usec -v printable -n 5 -b radio -f /data/local/log/logcat-radio.log

/system/bin/logcat -r 5120 -v threadtime -v usec -v printable -n 5 -b events -f /data/local/log/logcat-events.log

我们先看下logcat的如何对这个命令的实现的,在其main函数中,对f命令的实现如下:

case 'f':

if ((tail_time == log_time::EPOCH) && (tail_lines != 0)) {

tail_time = lastLogTime(optarg);

}

// redirect output to a file

g_outputFileName = optarg;

把文件名保存在g_outputFileName了,然后在main函数后面会调用setupOutput函数,我们来看下这个函数:

static void setupOutput()

{

if (g_outputFileName == NULL) {

g_outFD = STDOUT_FILENO;

} else {

if (set_sched_policy(0, SP_BACKGROUND) < 0) {

fprintf(stderr, "failed to set background scheduling policyn");

}

struct sched_param param;

memset(¶m, 0, sizeof(param));

if (sched_setscheduler((pid_t) 0, SCHED_BATCH, ¶m) < 0) {

fprintf(stderr, "failed to set to batch schedulern");

}

if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {

fprintf(stderr, "failed set to priorityn");

}

g_outFD = openLogFile (g_outputFileName);//得到了fd

if (g_outFD < 0) {

logcat_panic(false, "couldn't open output file");

}

struct stat statbuf;

if (fstat(g_outFD, &statbuf) == -1) {

close(g_outFD);

logcat_panic(false, "couldn't get output file statn");

}

if ((size_t) statbuf.st_size > SIZE_MAX || statbuf.st_size < 0) {

close(g_outFD);

logcat_panic(false, "invalid output file statn");

}

g_outByteCount = statbuf.st_size;

}

}

在这个函数中把文件的fd获取到了,是g_outFD。

最后我们可以在printBinary函数中往这个文件中写值。

void printBinary(struct log_msg *buf)

{

size_t size = buf->len();

TEMP_FAILURE_RETRY(write(g_outFD, buf, size));

}

也可以通过processBuffer来往文件写log。我们最后应该是通过processBuffer来写log的。

也就是上面的命令最终会把log保存在/data/local/log/logcat-radio.log文件下,当然这只是radio的log。

二、logcat获取logd中的log

而我们再看logcat的main最后是一个死循环,一直调用android_logger_list_read来从logd中获取log,然后再打印。

while (1) {

struct log_msg log_msg;

log_device_t* d;

int ret = android_logger_list_read(logger_list, &log_msg);//调用android_logger_list_read获取log

if (ret == 0) {

logcat_panic(false, "read: unexpected EOF!n");

}

if (ret < 0) {

if (ret == -EAGAIN) {

break;

}

if (ret == -EIO) {

logcat_panic(false, "read: unexpected EOF!n");

}

if (ret == -EINVAL) {

logcat_panic(false, "read: unexpected length.n");

}

logcat_panic(false, "logcat read failure");

}

for(d = devices; d; d = d->next) {

if (android_name_to_log_id(d->device) == log_msg.id()) {

break;

}

}

if (!d) {

g_devCount = 2; // set to Multiple

d = &unexpected;

d->binary = log_msg.id() == LOG_ID_EVENTS;

}

if (dev != d) {

dev = d;

maybePrintStart(dev, printDividers);

}

if (g_printBinary) {

printBinary(&log_msg);

} else {

processBuffer(dev, &log_msg);

}

}

android_logger_list_free(logger_list);

return EXIT_SUCCESS;

打印的话就是通过之前传进来的文件,写log到该文件的fd。

android_logger_list_read函数就是通过socket连接logd获取log。

int android_logger_list_read(struct logger_list *logger_list,

struct log_msg *log_msg)

{

int ret, e;

struct logger *logger;

struct sigaction ignore;

struct sigaction old_sigaction;

unsigned int old_alarm = 0;

if (!logger_list) {

return -EINVAL;

}

if (logger_list->mode & ANDROID_LOG_PSTORE) {

return android_logger_list_read_pstore(logger_list, log_msg);

}

if (logger_list->mode & ANDROID_LOG_NONBLOCK) {

memset(&ignore, 0, sizeof(ignore));

ignore.sa_handler = caught_signal;

sigemptyset(&ignore.sa_mask);

}

if (logger_list->sock < 0) {

char buffer[256], *cp, c;

int sock = socket_local_client("logdr",

ANDROID_SOCKET_NAMESPACE_RESERVED,

SOCK_SEQPACKET);

if (sock < 0) {

if ((sock == -1) && errno) {

return -errno;

}

return sock;

}上面logdr就是logcat到logd的socket。

三、总结

3.1 开3个进程保存不同log

我们手机上会开3个logcat进程来保存log,这3个进程会一直开着就是上面的死循环来不断保存log。

/system/bin/logcat -r 5120 -v threadtime -v usec -v printable -n 5 -f /data/local/log/logcat.log



/system/bin/logcat -r 5120 -v threadtime -v usec -v printable -n 5 -b radio -f /data/local/log/logcat-radio.log

/system/bin/logcat -r 5120 -v threadtime -v usec -v printable -n 5 -b events -f /data/local/log/logcat-events.log

3.2 kernel相关log

另外kernel的log是通过log_read_kern.c中的函数来实现的,而写的话通过logd_write_kern.c来实现的。

是通过节点来实现,而不是通过socket到logd实现的

节点:

dev/log/main

dev/log/radio

dev/log/system

dev/log/events

下篇博客我们主要说下logd是如何处理logcat的请求读log的。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。