logcat 通过读 /dev/socket/logd 套接字节点,以从 logd 进程中获取信息。

/logcat/logcat.cpp__logcat 方法中调用 android_logger_list_read

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
static int __logcat(android_logcat_context_internal* context) {
......
while (!context->stop &&
           (!context->maxCount || (context->printCount < context->maxCount))) {
        struct log_msg log_msg;
        int ret = android_logger_list_read(logger_list, &log_msg);
        if (!ret) {
            logcat_panic(context, HELP_FALSE, "read: unexpected EOF!\n");
            break;
        }
......

android_logger_list_read是 liblog/logger_read.c 中的接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
LIBLOG_ABI_PUBLIC int android_logger_list_read(struct logger_list* logger_list,
                                               struct log_msg* log_msg) {
  struct android_log_transport_context* transp;
  struct android_log_logger_list* logger_list_internal =
      (struct android_log_logger_list*)logger_list;

  int ret = init_transport_context(logger_list_internal);
  if (ret < 0) {
    return ret;
  }
......
}

其中调用了init_transport_context,该接口同样位于 liblog/logger_read.c ,主要实现如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
static int init_transport_context(struct android_log_logger_list* logger_list) {
......
__android_log_lock();
  /* mini __write_to_log_initialize() to populate transports */
  if (list_empty(&__android_log_transport_read) &&
      list_empty(&__android_log_persist_read)) {
    __android_log_config_read();
  }
  __android_log_unlock();
......
}

其中调用了__android_log_config_read,位于 /liblog/config_read.c,主要实现如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
LIBLOG_HIDDEN void __android_log_config_read() {
......
#if (FAKE_LOG_DEVICE == 0)
  if ((__android_log_transport == LOGGER_DEFAULT) ||
      (__android_log_transport & LOGGER_LOGD)) {
    extern struct android_log_transport_read logdLoggerRead;
    extern struct android_log_transport_read pmsgLoggerRead;

    __android_log_add_transport(&__android_log_transport_read, &logdLoggerRead);
    __android_log_add_transport(&__android_log_persist_read, &pmsgLoggerRead);
  }
#endif
}

其中调用了logdLoggerRead,位于 /liblog/logd_reader.c,主要实现如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
LIBLOG_HIDDEN struct android_log_transport_read logdLoggerRead = {
  .node = { &logdLoggerRead.node, &logdLoggerRead.node },
  .name = "logd",
  .available = logdAvailable,
  .version = logdVersion,
  .read = logdRead,
  .poll = logdPoll,
  .close = logdClose,
  .clear = logdClear,
  .getSize = logdGetSize,
  .setSize = logdSetSize,
  .getReadableSize = logdGetReadableSize,
  .getPrune = logdGetPrune,
  .setPrune = logdSetPrune,
  .getStats = logdGetStats,
};

其中通过logdRead函数指针为.read字段 进行赋值,logdRead的主要实现如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
static int logdRead(struct android_log_logger_list* logger_list,
                    struct android_log_transport_context* transp,
                    struct log_msg* log_msg) {
......
  ret = logdOpen(logger_list, transp);
  if (ret < 0) {
    return ret;
  }
......
   ret = recv(ret, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
......
}

里面调用了logdOpen来打开套接字logdr,而后返回logdRead进行recv

1
2
3
4
5
6
7
8
static int logdOpen(struct android_log_logger_list* logger_list,
                    struct android_log_transport_context* transp) {
......
sock = socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED,
                             SOCK_SEQPACKET);
......
	return sock;
}