一、logd LogReader监听logdr socket
在logd的main函数中会有一个监听logdr socket的LogReader类
我们来看下main函数的源码
LogReader *reader = new LogReader(logBuf);
if (reader->startListener()) {
exit(1);
}
再来看看LogReader的构造函数
LogReader::LogReader(LogBuffer *logbuf) :
SocketListener(getLogSocket(), true),
mLogbuf(*logbuf) {
}getLogSocket来获取logdr的socket
int LogReader::getLogSocket() {
static const char socketName[] = "logdr";
int sock = android_get_control_socket(socketName);
if (sock < 0) {
sock = socket_local_server(socketName,
ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_SEQPACKET);
}
return sock;
}
每次socket有请求数据都会调用onDataAvailable函数
bool LogReader::onDataAvailable(SocketClient *cli) {
......
uint64_t sequence = 1;
// Convert realtime to sequence number
if (start != log_time::EPOCH) {
class LogFindStart {
const pid_t mPid;
const unsigned mLogMask;
bool startTimeSet;
log_time &start;
uint64_t &sequence;
uint64_t last;
public:
LogFindStart(unsigned logMask, pid_t pid, log_time &start, uint64_t &sequence) :
mPid(pid),
mLogMask(logMask),
startTimeSet(false),
start(start),
sequence(sequence),
last(sequence) {
}
static int callback(const LogBufferElement *element, void *obj) {//回调
LogFindStart *me = reinterpret_cast(obj);
if ((!me->mPid || (me->mPid == element->getPid()))
&& (me->mLogMask & (1 << element->getLogId()))) {
if (me->start == element->getRealTime()) {
me->sequence = element->getSequence();
me->startTimeSet = true;
return -1;
} else {
if (me->start < element->getRealTime()) {
me->sequence = me->last;
me->startTimeSet = true;
return -1;
}
me->last = element->getSequence();
}
}
return false;
}
bool found() { return startTimeSet; }
} logFindStart(logMask, pid, start, sequence);
logbuf().flushTo(cli, sequence, FlushCommand::hasReadLogs(cli),
logFindStart.callback, &logFindStart);//
if (!logFindStart.found()) {
if (nonBlock) {
doSocketDelete(cli);
return false;
}
sequence = LogBufferElement::getCurrentSequence();
}
}
FlushCommand command(*this, nonBlock, tail, logMask, pid, sequence);
command.runSocketCommand(cli);
return true;
}我们先看下LogBuffer的flushTo函数
uint64_t LogBuffer::flushTo(
SocketClient *reader, const uint64_t start, bool privileged,
int (*filter)(const LogBufferElement *element, void *arg), void *arg) {
LogBufferElementCollection::iterator it;
uint64_t max = start;
uid_t uid = reader->getUid();
pthread_mutex_lock(&mLogElementsLock);
if (start <= 1) {//初始打印的值
// client wants to start from the beginning
it = mLogElements.begin();
} else {
// Client wants to start from some specified time. Chances are
// we are better off starting from the end of the time sorted list.
for (it = mLogElements.end(); it != mLogElements.begin(); /* do nothing */) {
--it;
LogBufferElement *element = *it;
if (element->getSequence() <= start) {
it++;
break;
}
}
}
for (; it != mLogElements.end(); ++it) {
LogBufferElement *element = *it;
if (!privileged && (element->getUid() != uid)) {
continue;
}
if (element->getSequence() <= start) {
continue;
}
// NB: calling out to another object with mLogElementsLock held (safe)
if (filter) {//传入的回调用来过滤
int ret = (*filter)(element, arg);
if (ret == false) {
continue;
}
if (ret != true) {
break;
}
}
pthread_mutex_unlock(&mLogElementsLock);
// range locking in LastLogTimes looks after us
max = element->flushTo(reader, this);//调用LogBufferElement的flushTo函数
if (max == element->FLUSH_ERROR) {
return max;
}
pthread_mutex_lock(&mLogElementsLock);
}
pthread_mutex_unlock(&mLogElementsLock);
return max;
}而LogBufferElement的flushTo函数就是往logcat的socket写log了。
uint64_t LogBufferElement::flushTo(SocketClient *reader, LogBuffer *parent) {
struct logger_entry_v3 entry;
memset(&entry, 0, sizeof(struct logger_entry_v3));
entry.hdr_size = sizeof(struct logger_entry_v3);
entry.lid = mLogId;
entry.pid = mPid;
entry.tid = mTid;
entry.sec = mRealTime.tv_sec;
entry.nsec = mRealTime.tv_nsec;
struct iovec iovec[2];
iovec[0].iov_base = &entry;
iovec[0].iov_len = sizeof(struct logger_entry_v3);
char *buffer = NULL;
if (!mMsg) {
entry.len = populateDroppedMessage(buffer, parent);
if (!entry.len) {
return mSequence;
}
iovec[1].iov_base = buffer;
} else {
entry.len = mMsgLen;
iovec[1].iov_base = mMsg;
}
iovec[1].iov_len = entry.len;
uint64_t retval = reader->sendDatav(iovec, 2) ? FLUSH_ERROR : mSequence;
if (buffer) {
free(buffer);
}
return retval;
}
我们再回过头看LogReader中的回调:
static int callback(const LogBufferElement *element, void *obj) {//回调
LogFindStart *me = reinterpret_cast(obj);
if ((!me->mPid || (me->mPid == element->getPid()))
&& (me->mLogMask & (1 << element->getLogId()))) {
if (me->start == element->getRealTime()) {
me->sequence = element->getSequence();
me->startTimeSet = true;
return -1;
} else {
if (me->start < element->getRealTime()) {
me->sequence = me->last;
me->startTimeSet = true;
return -1;
}
me->last = element->getSequence();
}
}
return false;
}
这个回调中没有返回true,说明在LogBuffer的flushTo函数中,执行到filter就执行不下去了。
for (; it != mLogElements.end(); ++it) {
LogBufferElement *element = *it;
if (!privileged && (element->getUid() != uid)) {
continue;
}
if (element->getSequence() <= start) {
continue;
}
// NB: calling out to another object with mLogElementsLock held (safe)
if (filter) {
int ret = (*filter)(element, arg);
if (ret == false) {
continue;
}
if (ret != true) {
break;
}
}
所以我们继续分析LogReader的onDataAvailable函数:
FlushCommand command(*this, nonBlock, tail, logMask, pid, sequence);
command.runSocketCommand(cli);调用了runSocketCommand函数:
void FlushCommand::runSocketCommand(SocketClient *client) {
LogTimeEntry *entry = NULL;
LastLogTimes × = mReader.logbuf().mTimes;
LogTimeEntry::lock();
LastLogTimes::iterator it = times.begin();
while(it != times.end()) {
entry = (*it);
if (entry->mClient == client) {//看传进来的client是否是同一个。
entry->triggerReader_Locked();//唤醒正在传log的线程
if (entry->runningReader_Locked()) {
LogTimeEntry::unlock();
return;
}
entry->incRef_Locked();
break;
}
it++;
}
if (it == times.end()) {
// Create LogTimeEntry in notifyNewLog() ?
if (mTail == (unsigned long) -1) {
LogTimeEntry::unlock();
return;
}
entry = new LogTimeEntry(mReader, client, mNonBlock, mTail, mLogMask, mPid, mStart);
times.push_front(entry);
}
client->incRef();
// release client and entry reference counts once done
entry->startReader_Locked();
LogTimeEntry::unlock();
}我们再来看LogTimeEntry的startReader_Locked函数
void LogTimeEntry::startReader_Locked(void) {
pthread_attr_t attr;
threadRunning = true;
if (!pthread_attr_init(&attr)) {
if (!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
if (!pthread_create(&mThread, &attr,
LogTimeEntry::threadStart, this)) {//开启线程
pthread_attr_destroy(&attr);
return;
}
}
pthread_attr_destroy(&attr);
}
threadRunning = false;
if (mClient) {
mClient->decRef();
}
decRef_Locked();
}threadStart函数代码如下:
void *LogTimeEntry::threadStart(void *obj) {
prctl(PR_SET_NAME, "logd.reader.per");
LogTimeEntry *me = reinterpret_cast(obj);
pthread_cleanup_push(threadStop, obj);
SocketClient *client = me->mClient;
if (!client) {
me->error();
return NULL;
}
LogBuffer &logbuf = me->mReader.logbuf();
bool privileged = FlushCommand::hasReadLogs(client);
me->leadingDropped = true;
lock();
while (me->threadRunning && !me->isError_Locked()) {
uint64_t start = me->mStart;
unlock();
if (me->mTail) {
logbuf.flushTo(client, start, privileged, FilterFirstPass, me);//第一次调用只是获取有多少条log
me->leadingDropped = true;
}
start = logbuf.flushTo(client, start, privileged, FilterSecondPass, me);//调用LogBuffer的flushTo函数,发送要选择的log
lock();
if (start == LogBufferElement::FLUSH_ERROR) {
me->error_Locked();
}
if (me->mNonBlock || !me->threadRunning || me->isError_Locked()) {
break;
}
me->cleanSkip_Locked();
pthread_cond_wait(&me->threadTriggeredCondition, ×Lock);//挂起线程
}
unlock();
pthread_cleanup_pop(true);
return NULL;
}主要循环调用LogBuffer的flushTo函数,然后挂起线程,直到下个同样的socket client请求来到,然后会唤醒这个线程,就会继续调用LogBuffer的flushTo。
二、总结
所以logcat会开3个进程不断的发送socket请求到logd,logd通过LogReader监听logdr socket然后处理各个socket请求获取log。LogReader会新建一个LogTimeEntry对象开启一个线程来调用LogBuffer的flushTo函数发送log,并且也会调用回调函数来过滤log,线程调用完挂起,直到下个相同的socket client请求,才会把这个线程恢复继续调用LogBuffer的flushTo发送log