天天看点

android log丢失(二)使用and4.4log kernel机制



在之前一篇博客我们是分析了logd丢失的原因,而且从增大logd缓冲区大小,以及增加白名单的方式临时解决调试问题。

这里我们就如何回到android4.4的log机制来分析。

当然还有一种方式,在android4.4的时候是不使用logd的机制的。使用的是往内存文件系统里面写log,写入dev/log/main  dev/log/radio等log。我们可以改回之前的模式。需要打几个补丁,这样就不会有丢失log的情况(不会有类似chatty的log)。

kernel的话我们可以看看dev/log目录下是否有main raidio等节点。如果有说明kernel是支持的,不需要打补丁了。只需改动system/core/liblog目录  以及修改板卡目录boardconfig.mk 还有selinux的权限。具体如下:

1. system/core/liblog补丁

地址:https://source.codeaurora.org/quic/la/platform/system/core/commit/?id=1b078a205c4ba34e2eaf5c5b248967ea4c08fb2c

From 1b078a205c4ba34e2eaf5c5b248967ea4c08fb2c Mon Sep 17 00:00:00 2001
From: Maria Yu <[email protected]>
Date: Wed, 23 Mar 2016 15:35:34 +0800
Subject: liblog: Fix compile error for using legacy kernel logger driver

Add log_event_write.c into liblog_sources file when using legacy
kernel logger driver. Add socket_local_client API in log_read_kern.
Fix the BIONIC define missing in logd_write_kern.

CRs-Fixed: 949708
Change-Id: If7a85e1d19fdd22581b6eb87096b39c2a700297e
---
 liblog/Android.mk        |   2 +-
 liblog/log_read_kern.c   | 169 +++++++++++++++++++++++++++++++++++++++++++++--
 liblog/logd_write_kern.c |   6 +-
 3 files changed, 170 insertions(+), 7 deletions(-)

diff --git a/liblog/Android.mk b/liblog/Android.mk
index 115dd79..1f113c5 100644
--- a/liblog/Android.mk
+++ b/liblog/Android.mk
@@ -27,7 +27,7 @@
 ifneq ($(TARGET_USES_LOGD),false)
 liblog_sources := logd_write.c log_event_write.c
 else
-liblog_sources := logd_write_kern.c
+liblog_sources := logd_write_kern.c log_event_write.c
 endif
 
 # some files must not be compiled when building against Mingw
diff --git a/liblog/log_read_kern.c b/liblog/log_read_kern.c
index 69b405c..b1b9a26 100644
--- a/liblog/log_read_kern.c
+++ b/liblog/log_read_kern.c
@@ -1,5 +1,5 @@
 /*
-** Copyright 2013-2014, The Android Open Source Project
+** Copyright 2013-2014,2016 The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
 #include <cutils/list.h>
 #include <log/log.h>
 #include <log/logger.h>
+#include <cutils/sockets.h>
 
 #define __LOGGERIO     0xAE
 
@@ -37,16 +38,174 @@
 #define LOGGER_GET_VERSION         _IO(__LOGGERIO, 5) /* abi version */
 #define LOGGER_SET_VERSION         _IO(__LOGGERIO, 6) /* abi version */
 
-typedef char bool;
-#define false (const bool)0
-#define true (const bool)1
-
 #define LOG_FILE_DIR "/dev/log/"
 
 /* timeout in milliseconds */
 #define LOG_TIMEOUT_FLUSH 5
 #define LOG_TIMEOUT_NEVER -1
 
+/* branchless on many architectures. */
+#define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
+
+#if (defined(USE_MINGW) || defined(HAVE_WINSOCK))
+#define WEAK static
+#else
+#define WEAK __attribute__((weak))
+#endif
+#ifndef __unused
+#define __unused __attribute__((unused))
+#endif
+
+/* Private copy of ../libcutils/socket_local_client.c prevent library loops */
+
+#ifdef HAVE_WINSOCK
+
+int WEAK socket_local_client(const char *name, int namespaceId, int type)
+{
+    errno = ENOSYS;
+    return -ENOSYS;
+}
+
+#else /* !HAVE_WINSOCK */
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/select.h>
+#include <sys/types.h>
+
+/* Private copy of ../libcutils/socket_local.h prevent library loops */
+#define FILESYSTEM_SOCKET_PREFIX "/tmp/"
+#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
+/* End of ../libcutils/socket_local.h */
+
+#define LISTEN_BACKLOG 4
+
+/* Documented in header file. */
+int WEAK socket_make_sockaddr_un(const char *name, int namespaceId,
+                                 struct sockaddr_un *p_addr, socklen_t *alen)
+{
+    memset (p_addr, 0, sizeof (*p_addr));
+    size_t namelen;
+
+    switch (namespaceId) {
+    case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
+#if defined(__linux__)
+        namelen  = strlen(name);
+
+        /* Test with length +1 for the *initial* '\0'. */
+        if ((namelen + 1) > sizeof(p_addr->sun_path)) {
+            goto error;
+        }
+
+        /*
+         * Note: The path in this case is *not* supposed to be
+         * '\0'-terminated. ("man 7 unix" for the gory details.)
+         */
+
+        p_addr->sun_path[0] = 0;
+        memcpy(p_addr->sun_path + 1, name, namelen);
+#else
+        /* this OS doesn't have the Linux abstract namespace */
+
+        namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
+        /* unix_path_max appears to be missing on linux */
+        if (namelen > sizeof(*p_addr)
+                - offsetof(struct sockaddr_un, sun_path) - 1) {
+            goto error;
+        }
+
+        strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
+        strcat(p_addr->sun_path, name);
+#endif
+        break;
+
+    case ANDROID_SOCKET_NAMESPACE_RESERVED:
+        namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
+        /* unix_path_max appears to be missing on linux */
+        if (namelen > sizeof(*p_addr)
+                - offsetof(struct sockaddr_un, sun_path) - 1) {
+            goto error;
+        }
+
+        strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
+        strcat(p_addr->sun_path, name);
+        break;
+
+    case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
+        namelen = strlen(name);
+        /* unix_path_max appears to be missing on linux */
+        if (namelen > sizeof(*p_addr)
+                - offsetof(struct sockaddr_un, sun_path) - 1) {
+            goto error;
+        }
+
+        strcpy(p_addr->sun_path, name);
+        break;
+
+    default:
+        /* invalid namespace id */
+        return -1;
+    }
+
+    p_addr->sun_family = AF_LOCAL;
+    *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
+    return 0;
+error:
+    return -1;
+}
+
+/**
+ * connect to peer named "name" on fd
+ * returns same fd or -1 on error.
+ * fd is not closed on error. that's your job.
+ *
+ * Used by AndroidSocketImpl
+ */
+int WEAK socket_local_client_connect(int fd, const char *name, int namespaceId,
+                                     int type __unused)
+{
+    struct sockaddr_un addr;
+    socklen_t alen;
+    int err;
+
+    err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
+
+    if (err < 0) {
+        goto error;
+    }
+
+    if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
+        goto error;
+    }
+
+    return fd;
+
+error:
+    return -1;
+}
+
+/**
+ * connect to peer named "name"
+ * returns fd or -1 on error
+ */
+int WEAK socket_local_client(const char *name, int namespaceId, int type)
+{
+    int s;
+
+    s = socket(AF_LOCAL, type, 0);
+    if(s < 0) return -1;
+
+    if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
+        close(s);
+        return -1;
+    }
+
+    return s;
+}
+
+#endif /* !HAVE_WINSOCK */
+/* End of ../libcutils/socket_local_client.c */
+
 #define logger_for_each(logger, logger_list) \
     for (logger = node_to_item((logger_list)->node.next, struct logger, node); \
          logger != node_to_item(&(logger_list)->node, struct logger, node); \
diff --git a/liblog/logd_write_kern.c b/liblog/logd_write_kern.c
index 8742b34..bddfbdd 100644
--- a/liblog/logd_write_kern.c
+++ b/liblog/logd_write_kern.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2014 The Android Open Source Project
+ * Copyright (C) 2007-2014,2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -26,7 +26,9 @@
 #include <time.h>
 #include <unistd.h>
 
+#ifdef __BIONIC__
 #include <android/set_abort_message.h>
+#endif
 
 #include <log/log.h>
 #include <log/logd.h>
@@ -167,9 +169,11 @@ int __android_log_buf_write(int bufID, int prio, const char *tag, const char *ms
             tag = tmp_tag;
     }
 
+#ifdef __BIONIC__
     if (prio == ANDROID_LOG_FATAL) {
         android_set_abort_message(msg);
     }
+#endif
 
     vec[0].iov_base   = (unsigned char *) &prio;
     vec[0].iov_len    = 1;
-- 
cgit v1.1
           

2. selinux权限

加上domain对log_device的读写权限

diff --git a/domain.te b/domain.te
index 0f6c6da..4e0f541 100644
--- a/domain.te
+++ b/domain.te
@@ -88,6 +88,8 @@ allow domain null_device:chr_file rw_file_perms;
allow domain zero_device:chr_file rw_file_perms;
allow domain ashmem_device:chr_file rw_file_perms;
allow domain binder_device:chr_file rw_file_perms;
+allow domain log_device:dir search;
+allow domain log_device:chr_file rw_file_perms;
allow domain ptmx_device:chr_file rw_file_perms;
allow domain alarm_device:chr_file r_file_perms;
allow domain urandom_device:chr_file rw_file_perms;
           

3. 去除logd的编译

只要在所编译版本的BoardConfig.mk中加入TARGET_USES_LOGD := false

4. kernel相关补丁

kernel部分如果没有合入补丁的话:

kernel补丁: https://us.codeaurora.org/cgit/quic/la/kernel/msm-3.18/commit/?id=

5ec14761ae4f9e0c65519a6d954da0a08f59fa80

https://us.codeaurora.org/cgit/quic/la/kernel/msm-3.18/commit/?id=

1813ebe46a4d61423be3c121484f298abdbaf86d

kernel的kconfig: 在kernel的kConfig文件中加上CONFIG_ANDROID_LOGGER=y

5. 后续

这样我们就可以回到android4.4的log机制,但是常规我们还是使用现在logd的机制,因为这样应该更节省内存开销会用户更加友好,而如果我们平时开发遇到丢失log很严重的问题就要重新烧版本比较麻烦,因此我考虑做一种可以动态切换的机制。