在之前一篇博客我们是分析了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很严重的问题就要重新烧版本比较麻烦,因此我考虑做一种可以动态切换的机制。
原文地址: http://blog.csdn.net/kc58236582/article/details/72276041