LOG_ID_MAIN = 0, LOG_ID_RADIO = 1, LOG_ID_EVENTS = 2, LOG_ID_SYSTEM = 3, LOG_ID_CRASH = 4, LOG_ID_SECURITY = 5, LOG_ID_KERNEL = 6, /* place last, third-parties can not use it */
LOG_ID_MAX } log_id_t;
// system/core/logd/LogStatistics.h #define log_id_for_each(i) \ for (log_id_t i = LOG_ID_MIN; (i) < LOG_ID_MAX; (i) = (log_id_t)((i) + 1))
monotonic 表示时间的格式,如果为 true,表示使用的是 CPU 的 up time(系统上电后从 0 开始计数)。一般我们用的是 real time(就是我们一般说的时间的概念)。这里就假定它是 false 好了。
// set the total space allocated to "id" int LogBuffer::setSize(log_id_t id, unsignedlong size) { // Reasonable limits ... if (!__android_logger_valid_buffer_size(size)) { return-1; } pthread_mutex_lock(&mLogElementsLock); log_buffer_size(id) = size; pthread_mutex_unlock(&mLogElementsLock); return0; }
bool lastMonotonic = monotonic; monotonic = android_log_clockid() == CLOCK_MONOTONIC; if (lastMonotonic != monotonic) { // // Fixup all timestamps, may not be 100% accurate, but better than // throwing what we have away when we get 'surprised' by a change. // In-place element fixup so no need to check reader-lock. Entries // should already be in timestamp order, but we could end up with a // few out-of-order entries if new monotonics come in before we // are notified of the reinit change in status. A Typical example would // be: // --------- beginning of system // 10.494082 184 201 D Cryptfs : Just triggered post_fs_data // --------- beginning of kernel // 0.000000 0 0 I : Initializing cgroup subsys // as the act of mounting /data would trigger persist.logd.timestamp to // be corrected. 1/30 corner case YMMV. // pthread_mutex_lock(&mLogElementsLock); LogBufferElementCollection::iterator it = mLogElements.begin(); while ((it != mLogElements.end())) { LogBufferElement* e = *it; if (monotonic) { if (!android::isMonotonic(e->mRealTime)) { LogKlog::convertRealToMonotonic(e->mRealTime); } } else { if (android::isMonotonic(e->mRealTime)) { LogKlog::convertMonotonicToReal(e->mRealTime); } } ++it; } pthread_mutex_unlock(&mLogElementsLock); }
// We may have been triggered by a SIGHUP. Release any sleeping reader // threads to dump their current content. // // NB: this is _not_ performed in the context of a SIGHUP, it is // performed during startup, and in context of reinit administrative thread LogTimeEntry::lock();
LastLogTimes::iterator times = mTimes.begin(); while (times != mTimes.end()) { LogTimeEntry* entry = (*times); if (entry->owned_Locked()) { entry->triggerReader_Locked(); } times++; }
// LogReader listens on /dev/socket/logdr. When a client // connects, log entries in the LogBuffer are written to the client.
LogReader* reader = new LogReader(logBuf); if (reader->startListener()) { exit(1); }
// LogListener listens on /dev/socket/logdw for client // initiated log messages. New log entries are added to LogBuffer // and LogReader is notified to send updates to connected clients.
LogListener* swl = new LogListener(logBuf, reader); // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value if (swl->startListener(600)) { exit(1); }
structucred { pid_t pid; /* process ID of the sending process */ uid_t uid; /* user ID of the sending process */ gid_t gid; /* group ID of the sending process */ };
while(1) { SocketClientCollection::iterator it; fd_set read_fds; int rc = 0; int max = -1;
FD_ZERO(&read_fds);
if (mListen) { max = mSock; FD_SET(mSock, &read_fds); }
FD_SET(mCtrlPipe[0], &read_fds); if (mCtrlPipe[0] > max) max = mCtrlPipe[0];
pthread_mutex_lock(&mClientsLock); for (it = mClients->begin(); it != mClients->end(); ++it) { // NB: calling out to an other object with mClientsLock held (safe) int fd = (*it)->getSocket(); FD_SET(fd, &read_fds); if (fd > max) { max = fd; } } pthread_mutex_unlock(&mClientsLock); SLOGV("mListen=%d, max=%d, mSocketName=%s", mListen, max, mSocketName); if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) { if (errno == EINTR) continue; SLOGE("select failed (%s) mListen=%d, max=%d", strerror(errno), mListen, max); sleep(1); continue; } elseif (!rc) continue;
if (FD_ISSET(mCtrlPipe[0], &read_fds)) { char c = CtrlPipe_Shutdown; TEMP_FAILURE_RETRY(read(mCtrlPipe[0], &c, 1)); if (c == CtrlPipe_Shutdown) { break; } continue; } if (mListen && FD_ISSET(mSock, &read_fds)) { int c = TEMP_FAILURE_RETRY(accept4(mSock, nullptr, nullptr, SOCK_CLOEXEC)); if (c < 0) { SLOGE("accept failed (%s)", strerror(errno)); sleep(1); continue; } pthread_mutex_lock(&mClientsLock); mClients->push_back(new SocketClient(c, true, mUseCmdNum)); pthread_mutex_unlock(&mClientsLock); }
/* Add all active clients to the pending list first */ pendingList.clear(); pthread_mutex_lock(&mClientsLock); for (it = mClients->begin(); it != mClients->end(); ++it) { SocketClient* c = *it; // NB: calling out to an other object with mClientsLock held (safe) int fd = c->getSocket(); if (FD_ISSET(fd, &read_fds)) { pendingList.push_back(c); c->incRef(); } } pthread_mutex_unlock(&mClientsLock);
/* Process the pending list, since it is owned by the thread, * there is no need to lock it */ while (!pendingList.empty()) { /* Pop the first item from the list */ it = pendingList.begin(); SocketClient* c = *it; pendingList.erase(it); /* Process it, if false is returned, remove from list */ if (!onDataAvailable(c)) { release(c, false); } c->decRef(); } } }
// system/core/libsysutils/src/SocketListener.cpp bool SocketListener::release(SocketClient* c, bool wakeup) { bool ret = false; /* if our sockets are connection-based, remove and destroy it */ if (mListen && c) { /* Remove the client from our array */ SLOGV("going to zap %d for %s", c->getSocket(), mSocketName); pthread_mutex_lock(&mClientsLock); SocketClientCollection::iterator it; for (it = mClients->begin(); it != mClients->end(); ++it) { if (*it == c) { mClients->erase(it); ret = true; break; } } pthread_mutex_unlock(&mClientsLock); if (ret) { ret = c->decRef(); if (wakeup) { char b = CtrlPipe_Wakeup; TEMP_FAILURE_RETRY(write(mCtrlPipe[1], &b, 1)); } } } return ret; }