【Android】Android 7中logcat读logdr的处理

logcat通过读/dev/socket/logdr这个socket节点来从logd进程中获取信息,

这个处理在Android 6的logcat代码中很清楚的就可以看到。

但是Android 7里读logdr写的很晦涩,这里我们来看看Android 7里logcat读logdr的处理。

在Android 6中,

可以很清晰的看到使用android_logger_list_read来读logdr

/system/core/logcat/logcat.cpp

int main(int argc, char **argv)
{
… …
    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定义在

/system/core/liblog/log_read.c

int android_logger_list_read(struct logger_list *logger_list,
                             struct log_msg *log_msg)
{
        int sock = socket_local_client("logdr",
                                       ANDROID_SOCKET_NAMESPACE_RESERVED,
                                       SOCK_SEQPACKET);

 

 

在Android 7中

/system/core/logcat/logcat.cpp

同样是调用android_logger_list_read

    while (!g_maxCount || (g_printCount < g_maxCount)) {
        struct log_msg log_msg;
        log_device_t* d;
        int ret = android_logger_list_read(logger_list, &log_msg);

但是android_logger_list_read的实现却面目全非了,定义在

/system/core/liblog/logger_read.c

里面

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;
    }
 
    /* at least one transport */
    transp = node_to_item(logger_list_internal->transport.next,
                          struct android_log_transport_context, node);
 
    /* more than one transport? */
    if (transp->node.next != &logger_list_internal->transport) {
        /* Poll and merge sort the entries if from multiple transports */
        struct android_log_transport_context *oldest = NULL;
        int ret;
        int polled = 0;
        do {
            if (polled) {
                sched_yield();
            }
            ret = -1000;
            polled = 0;
            do {
                int retval = transp->ret;
                if ((retval > 0) && !transp->logMsg.entry.len) {
                    if (!transp->transport->read) {
                        retval = transp->ret = 0;
                    } else if ((logger_list_internal->mode &
                                ANDROID_LOG_NONBLOCK) ||
                            !transp->transport->poll) {
                        retval = transp->ret = (*transp->transport->read)(
                                logger_list_internal,
                                transp,
                                &transp->logMsg);
                    } else {
                        int pollval = (*transp->transport->poll)(
                                logger_list_internal, transp);
                        if (pollval <= 0) {
                            sched_yield();
                            pollval = (*transp->transport->poll)(
                                    logger_list_internal, transp);
                        }
                        polled = 1;
                        if (pollval < 0) {
                            if ((pollval == -EINTR) || (pollval == -EAGAIN)) {
                                return -EAGAIN;
                            }
                            retval = transp->ret = pollval;
                        } else if (pollval > 0) {
                            retval = transp->ret = (*transp->transport->read)(
                                    logger_list_internal,
                                    transp,
                                    &transp->logMsg);
                        }
                    }
                }
                if (ret < retval) {
                    ret = retval;
                }
                if ((transp->ret > 0) && transp->logMsg.entry.len &&
                        (!oldest ||
                            (oldest->logMsg.entry.sec >
                                transp->logMsg.entry.sec) ||
                            ((oldest->logMsg.entry.sec ==
                                    transp->logMsg.entry.sec) &&
                                (oldest->logMsg.entry.nsec >
                                    transp->logMsg.entry.nsec)))) {
                    oldest = transp;
                }
                transp = node_to_item(transp->node.next,
                                      struct android_log_transport_context,
                                      node);
            } while (transp != node_to_item(
                    &logger_list_internal->transport,
                    struct android_log_transport_context,
                    node));
            if (!oldest &&
                    (logger_list_internal->mode & ANDROID_LOG_NONBLOCK)) {
                return (ret < 0) ? ret : -EAGAIN;
            }
            transp = node_to_item(logger_list_internal->transport.next,
                                  struct android_log_transport_context, node);
        } while (!oldest && (ret > 0));
        if (!oldest) {
            return ret;
        }
        memcpy(log_msg, &oldest->logMsg, oldest->logMsg.entry.len +
                    (oldest->logMsg.entry.hdr_size ?
                        oldest->logMsg.entry.hdr_size :
                        sizeof(struct logger_entry)));
        oldest->logMsg.entry.len = 0; /* Mark it as copied */
        return oldest->ret;
    }
 
    /* if only one, no need to copy into transport_context and merge-sort */
    return (transp->transport->read)(logger_list_internal, transp, log_msg);
}

并没有看到logdr

 

到底是怎么读的呢

init_transport_context

中有

    if (list_empty(&__android_log_transport_read) &&
            list_empty(&__android_log_persist_read)) {
        __android_log_config_read();
    }

 

/system/core/liblog/config_read.c

LIBLOG_HIDDEN void __android_log_config_read() {
#if (FAKE_LOG_DEVICE == 0)
    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

/system/core/liblog/logd_reader.c

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,
};

 

static int logdRead(struct android_log_logger_list *logger_list,
                    struct android_log_transport_context *transp,
                    struct log_msg *log_msg)
{
    int ret, e;
    struct sigaction ignore;
    struct sigaction old_sigaction;
    unsigned int old_alarm = 0;
 
    ret = logdOpen(logger_list, transp);
    if (ret < 0) {
        return ret;
    }
 
    memset(log_msg, 0, sizeof(*log_msg));
 
    if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
        memset(&ignore, 0, sizeof(ignore));
        ignore.sa_handler = caught_signal;
        sigemptyset(&ignore.sa_mask);
        /* particularily useful if tombstone is reporting for logd */
        sigaction(SIGALRM, &ignore, &old_sigaction);
        old_alarm = alarm(30);
    }
 
    /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
    ret = recv(ret, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
    e = errno;

 

里面调用了logdOpen来打开logdr

static int logdOpen(struct android_log_logger_list *logger_list,
                    struct android_log_transport_context *transp)
{
    struct android_log_logger *logger;
    struct sigaction ignore;
    struct sigaction old_sigaction;
    unsigned int old_alarm = 0;
    char buffer[256], *cp, c;
    int e, ret, remaining;
 
    int sock = transp->context.sock;
    if (sock > 0) {
        return sock;
    }
 
    if (!logger_list) {
        return -EINVAL;
    }
 
    sock = socket_local_client("logdr",
                               ANDROID_SOCKET_NAMESPACE_RESERVED,
                               SOCK_SEQPACKET);
    if (sock == 0) {
        /* Guarantee not file descriptor zero */
        int newsock = socket_local_client("logdr",
                                   ANDROID_SOCKET_NAMESPACE_RESERVED,
                                   SOCK_SEQPACKET);
        close(sock);
        sock = newsock;
    }
    if (sock <= 0) {
        if ((sock == -1) && errno) {
            return -errno;
        }
        return sock;
    }

 



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值