在之前一篇博客我们是分析了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补丁
From 1b078a205c4ba34e2eaf5c5b248967ea4c08fb2c Mon Sep 17 00:00:00 2001
From: Maria Yu <aiquny@codeaurora.org>
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
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很严重的问题就要重新烧版本比较麻烦,因此我考虑做一种可以动态切换的机制。