1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > android 6.0 logcat机制(二)logcat从logd中获取log保存到文件中

android 6.0 logcat机制(二)logcat从logd中获取log保存到文件中

时间:2022-12-18 06:22:47

相关推荐

android 6.0 logcat机制(二)logcat从logd中获取log保存到文件中

这篇博客分析的是logcat是如何获取logd中的log,然后写入文件。

一、设置保存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命令的实现如下:

[java]view plaincopycase'f': if((tail_time==log_time::EPOCH)&&(tail_lines!=0)){ tail_time=lastLogTime(optarg); } //redirectoutputtoafile g_outputFileName=optarg;

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

[java]view plaincopystaticvoidsetupOutput() { if(g_outputFileName==NULL){ g_outFD=STDOUT_FILENO; }else{ if(set_sched_policy(0,SP_BACKGROUND)<0){ fprintf(stderr,"failedtosetbackgroundschedulingpolicy\n"); } structsched_paramparam; memset(¶m,0,sizeof(param)); if(sched_setscheduler((pid_t)0,SCHED_BATCH,¶m)<0){ fprintf(stderr,"failedtosettobatchscheduler\n"); } if(setpriority(PRIO_PROCESS,0,ANDROID_PRIORITY_BACKGROUND)<0){ fprintf(stderr,"failedsettopriority\n"); } g_outFD=openLogFile(g_outputFileName);//得到了fd if(g_outFD<0){ logcat_panic(false,"couldn'topenoutputfile"); } structstatstatbuf; if(fstat(g_outFD,&statbuf)==-1){ close(g_outFD); logcat_panic(false,"couldn'tgetoutputfilestat\n"); } if((size_t)statbuf.st_size>SIZE_MAX||statbuf.st_size<0){ close(g_outFD); logcat_panic(false,"invalidoutputfilestat\n"); } g_outByteCount=statbuf.st_size; } }

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

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

[java]view plaincopyvoidprintBinary(structlog_msg*buf) { size_tsize=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,然后再打印。

[java]view plaincopywhile(1){ structlog_msglog_msg; log_device_t*d; intret=android_logger_list_read(logger_list,&log_msg);//调用android_logger_list_read获取log if(ret==0){ logcat_panic(false,"read:unexpectedEOF!\n"); } if(ret<0){ if(ret==-EAGAIN){ break; } if(ret==-EIO){ logcat_panic(false,"read:unexpectedEOF!\n"); } if(ret==-EINVAL){ logcat_panic(false,"read:unexpectedlength.\n"); } logcat_panic(false,"logcatreadfailure"); } for(d=devices;d;d=d->next){ if(android_name_to_log_id(d->device)==log_msg.id()){ break; } } if(!d){ g_devCount=2;//settoMultiple 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); returnEXIT_SUCCESS;

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

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

[java]view plaincopyintandroid_logger_list_read(structlogger_list*logger_list, structlog_msg*log_msg) { intret,e; structlogger*logger; structsigactionignore; structsigactionold_sigaction; unsignedintold_alarm=0; if(!logger_list){ return-EINVAL; } if(logger_list->mode&ANDROID_LOG_PSTORE){ returnandroid_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){ charbuffer[256],*cp,c; intsock=socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET); if(sock<0){ if((sock==-1)&&errno){ return-errno; } returnsock; } 上面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的。

原文地址:/kc58236582/article/details/51075591

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。