android log丢失(三)动态切换logd机制和kernel机制
之前我们分析了如何修改版本使log机制变成kernel的log机制。这篇博客我们继续修改可以动态切换,这样方便平时log丢失时调试。
我们先来看liblog库的编译mk文件,这个文件中主要修改了对使用使用logd 使用不同文件进行编译这块做了修改,增加了log_write_common.c 和log_read_common.c两个通用文件。
[html] view plain copy- #
- # Copyright (C) 2008-2014 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.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- #
- LOCAL_PATH := $(my-dir)
- include $(CLEAR_VARS)
- # This is what we want to do:
- # liblog_cflags := $(shell \
- # sed -n \
- # 's/^ [0−9]∗ [ \t]*liblog[ \t].*/-DLIBLOG_LOG_TAG=\1/p' \
- # $(LOCAL_PATH)/event.logtags)
- # so make sure we do not regret hard-coding it as follows:
- liblog_cflags := -DLIBLOG_LOG_TAG=1005
- #ifneq ($(TARGET_USES_LOGD),false)//注释了 不需要区分使用使用logd
- #liblog_sources := logd_write.c log_event_write.c
- #else
- #liblog_sources := logd_write_kern.c log_event_write.c
- #endif
- liblog_sources := log_write_common.c log_event_write.c//增加log_write_common.c
- # some files must not be compiled when building against Mingw
- # they correspond to features not used by our host development tools
- # which are also hard or even impossible to port to native Win32
- ifeq ($(strip $(USE_MINGW)),)
- liblog_sources += \
- event_tag_map.c
- else
- liblog_sources += \
- uio.c
- endif
- liblog_host_sources := $(liblog_sources) fake_log_device.c event.logtags
- liblog_target_sources := $(liblog_sources) log_time.cpp log_is_loggable.c
- ifeq ($(strip $(USE_MINGW)),)
- liblog_target_sources += logprint.c
- endif
- #ifneq ($(TARGET_USES_LOGD),false)//注释了,不用区分是否使用logd
- #liblog_target_sources += log_read.c
- #else
- #liblog_target_sources += log_read_kern.c
- #endif
- liblog_target_sources += log_read_common.c//增加log_read_common.c
- # Shared and static library for host
- # ========================================================
- LOCAL_MODULE := liblog
- LOCAL_SRC_FILES := $(liblog_host_sources)
- LOCAL_CFLAGS := -DFAKE_LOG_DEVICE=1 -Werror $(liblog_cflags)
- LOCAL_MULTILIB := both
- include $(BUILD_HOST_STATIC_LIBRARY)
- include $(CLEAR_VARS)
- LOCAL_MODULE := liblog
- LOCAL_WHOLE_STATIC_LIBRARIES := liblog
- ifeq ($(strip $(HOST_OS)),linux)
- LOCAL_LDLIBS := -lrt
- endif
- LOCAL_MULTILIB := both
- include $(BUILD_HOST_SHARED_LIBRARY)
- # Shared and static library for target
- # ========================================================
- include $(CLEAR_VARS)
- LOCAL_MODULE := liblog
- LOCAL_SRC_FILES := $(liblog_target_sources)
- LOCAL_CFLAGS := -Werror $(liblog_cflags)
- include $(BUILD_STATIC_LIBRARY)
- include $(CLEAR_VARS)
- LOCAL_MODULE := liblog
- LOCAL_WHOLE_STATIC_LIBRARIES := liblog
- LOCAL_CFLAGS := -Werror $(liblog_cflags)
- # TODO: This is to work around b/19059885. Remove after root cause is fixed
- LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
- include $(BUILD_SHARED_LIBRARY)
- include $(call first-makefiles-under,$(LOCAL_PATH))
我们先来看log_read_common.c文件,这样主要就是将原来的logd_write.c 和logd_write_kern.c 文件进行合并。一些对外的接口,统一使用use_logd这个全局变量来控制,选择logd的函数,还是kernel的函数(logd的函数和kernel的函数就是static函数了,不用对外)。另外在__write_to_log_init函数中,第一次初始化的使用,先看system/etc/disable_logd是否有这样一个文件,有就将use_logd为0,代表使用kernel机制。
[cpp] view plain copy- /*
- * Copyright (C) 2007-2014 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #if (FAKE_LOG_DEVICE == 0)
- #include
- #endif
- #include
- #include
- #if !defined(_WIN32)
- #include
- #endif
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #if (FAKE_LOG_DEVICE == 0)
- #include
- #include
- #endif
- #include
- #include
- #ifdef __BIONIC__
- #include
- #endif
- #include
- #include
- #include
- #include
- #include
- #include
- #define LOGGER_LOG_MAIN "log/main"
- #define LOGGER_LOG_RADIO "log/radio"
- #define LOGGER_LOG_EVENTS "log/events"
- #define LOGGER_LOG_SYSTEM "log/system"
- #define LOG_BUF_SIZE 1024
- #if FAKE_LOG_DEVICE
- /* This will be defined when building for the host. */
- #include "fake_log_device.h"
- #endif
- #define log_open(pathname, flags) open(pathname, (flags) | O_CLOEXEC)
- #define log_writev(filedes, vector, count) writev(filedes, vector, count)
- #define log_close(filedes) close(filedes)
- static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
- static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
- #if !defined(_WIN32)
- static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
- #endif
- #ifndef __unused
- #define __unused __attribute__((__unused__))
- #endif
- static int8_t use_logd = 1;//做区分
- #if FAKE_LOG_DEVICE
- static int log_fds_fake[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1 };
- #else
- static int logd_fd = -1;
- static int pstore_fd = -1;
- #endif
- static int log_fds_kernel[(int)LOG_ID_MAX] = { -1, -1, -1, -1 };
- /*
- * This is used by the C++ code to decide if it should write logs through
- * the C code. Basically, if /dev/socket/logd is available, we're running in
- * the simulator rather than a desktop tool and want to use the device.
- */
- static enum {
- kLogUninitialized, kLogNotAvailable, kLogAvailable
- } g_log_status = kLogUninitialized;
- static int __android_log_dev_available_logd(void)
- {
- if (g_log_status == kLogUninitialized) {
- if (access("/dev/socket/logdw", W_OK) == 0)
- g_log_status = kLogAvailable;
- else
- g_log_status = kLogNotAvailable;
- }
- return (g_log_status == kLogAvailable);
- }
- static int __android_log_dev_available_kernel(void)
- {
- if (g_log_status == kLogUninitialized) {
- if (access("/dev/"LOGGER_LOG_MAIN, W_OK) == 0)
- g_log_status = kLogAvailable;
- else
- g_log_status = kLogNotAvailable;
- }
- return (g_log_status == kLogAvailable);
- }
- int __android_log_dev_available(void)
- {
- if (use_logd) {
- return __android_log_dev_available_logd();
- } else {
- return __android_log_dev_available_kernel();
- }
- }
- /* log_init_lock assumed */
- static int __write_to_log_initialize()
- {
- int i, ret = 0;
- #if FAKE_LOG_DEVICE
- for (i = 0; i < LOG_ID_MAX; i++) {
- char buf[sizeof("/dev/log_system")];
- snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i));
- log_fds_fake[i] = fakeLogOpen(buf, O_WRONLY);
- }
- #else
- if (pstore_fd < 0) {
- pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY));
- }
- if (logd_fd < 0) {
- i = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0));
- if (i < 0) {
- ret = -errno;
- } else if (TEMP_FAILURE_RETRY(fcntl(i, F_SETFL, O_NONBLOCK)) < 0) {
- ret = -errno;
- close(i);
- } else {
- struct sockaddr_un un;
- memset(&un, 0, sizeof(struct sockaddr_un));
- un.sun_family = AF_UNIX;
- strcpy(un.sun_path, "/dev/socket/logdw");
- if (TEMP_FAILURE_RETRY(connect(i, (struct sockaddr *)&un,
- sizeof(struct sockaddr_un))) < 0) {
- ret = -errno;
- close(i);
- } else {
- logd_fd = i;
- }
- }
- }
- #endif
- return ret;
- }
- static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
- {
- ssize_t ret;
- #if FAKE_LOG_DEVICE
- int log_fd;
- if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) {
- log_fd = log_fds_fake[(int)log_id];
- } else {
- return -EBADF;
- }
- do {
- ret = fakeLogWritev(log_fd, vec, nr);
- if (ret < 0) {
- ret = -errno;
- }
- } while (ret == -EINTR);
- #else
- static const unsigned header_length = 2;
- struct iovec newVec[nr + header_length];
- android_log_header_t header;
- android_pmsg_log_header_t pmsg_header;
- struct timespec ts;
- size_t i, payload_size;
- static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */
- static pid_t last_pid = (pid_t) -1;
- static atomic_int_fast32_t dropped;
- if (!nr) {
- return -EINVAL;
- }
- if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */
- last_uid = getuid();
- }
- if (last_pid == (pid_t) -1) {
- last_pid = getpid();
- }
- /*
- * struct {
- * // what we provide to pstore
- * android_pmsg_log_header_t pmsg_header;
- * // what we provide to socket
- * android_log_header_t header;
- * // caller provides
- * union {
- * struct {
- * char prio;
- * char payload[];
- * } string;
- * struct {
- * uint32_t tag
- * char payload[];
- * } binary;
- * };
- * };
- */
- clock_gettime(CLOCK_REALTIME, &ts);
- pmsg_header.magic = LOGGER_MAGIC;
- pmsg_header.len = sizeof(pmsg_header) + sizeof(header);
- pmsg_header.uid = last_uid;
- pmsg_header.pid = last_pid;
- header.tid = gettid();
- header.realtime.tv_sec = ts.tv_sec;
- header.realtime.tv_nsec = ts.tv_nsec;
- newVec[0].iov_base = (unsigned char *) &pmsg_header;
- newVec[0].iov_len = sizeof(pmsg_header);
- newVec[1].iov_base = (unsigned char *) &header;
- newVec[1].iov_len = sizeof(header);
- if (logd_fd > 0) {
- int32_t snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
- if (snapshot) {
- android_log_event_int_t buffer;
- header.id = LOG_ID_EVENTS;
- buffer.header.tag = htole32(LIBLOG_LOG_TAG);
- buffer.payload.type = EVENT_TYPE_INT;
- buffer.payload.data = htole32(snapshot);
- newVec[2].iov_base = &buffer;
- newVec[2].iov_len = sizeof(buffer);
- ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2));
- if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
- atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
- }
- }
- }
- header.id = log_id;
- for (payload_size = 0, i = header_length; i < nr + header_length; i++) {
- newVec[i].iov_base = vec[i - header_length].iov_base;
- payload_size += newVec[i].iov_len = vec[i - header_length].iov_len;
- if (payload_size > LOGGER_ENTRY_MAX_PAYLOAD) {
- newVec[i].iov_len -= payload_size - LOGGER_ENTRY_MAX_PAYLOAD;
- if (newVec[i].iov_len) {
- ++i;
- }
- payload_size = LOGGER_ENTRY_MAX_PAYLOAD;
- break;
- }
- }
- pmsg_header.len += payload_size;
- if (pstore_fd >= 0) {
- TEMP_FAILURE_RETRY(writev(pstore_fd, newVec, i));
- }
- if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */
- /*
- * ignore log messages we send to ourself (logd).
- * Such log messages are often generated by libraries we depend on
- * which use standard Android logging.
- */
- return 0;
- }
- if (logd_fd < 0) {
- return -EBADF;
- }
- /*
- * The write below could be lost, but will never block.
- *
- * To logd, we drop the pmsg_header
- *
- * ENOTCONN occurs if logd dies.
- * EAGAIN occurs if logd is overloaded.
- */
- ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1));
- if (ret < 0) {
- ret = -errno;
- if (ret == -ENOTCONN) {
- #if !defined(_WIN32)
- pthread_mutex_lock(&log_init_lock);
- #endif
- close(logd_fd);
- logd_fd = -1;
- ret = __write_to_log_initialize();
- #if !defined(_WIN32)
- pthread_mutex_unlock(&log_init_lock);
- #endif
- if (ret < 0) {
- return ret;
- }
- ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1));
- if (ret < 0) {
- ret = -errno;
- }
- }
- }
- if (ret > (ssize_t)sizeof(header)) {
- ret -= sizeof(header);
- } else if (ret == -EAGAIN) {
- atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
- }
- #endif
- return ret;
- }
- #if FAKE_LOG_DEVICE
- static const char *LOG_NAME[LOG_ID_MAX] = {
- [LOG_ID_MAIN] = "main",
- [LOG_ID_RADIO] = "radio",
- [LOG_ID_EVENTS] = "events",
- [LOG_ID_SYSTEM] = "system",
- [LOG_ID_CRASH] = "crash",
- [LOG_ID_KERNEL] = "kernel",
- };
- const char *android_log_id_to_name(log_id_t log_id)
- {
- if (log_id >= LOG_ID_MAX) {
- log_id = LOG_ID_MAIN;
- }
- return LOG_NAME[log_id];
- }
- #endif
- static int __write_to_log_init_logd(log_id_t log_id, struct iovec *vec, size_t nr)
- {
- #if !defined(_WIN32)
- pthread_mutex_lock(&log_init_lock);
- #endif
- if (write_to_log == __write_to_log_init) {
- int ret;
- ret = __write_to_log_initialize();
- if (ret < 0) {
- #if !defined(_WIN32)
- pthread_mutex_unlock(&log_init_lock);
- #endif
- #if (FAKE_LOG_DEVICE == 0)
- if (pstore_fd >= 0) {
- __write_to_log_daemon(log_id, vec, nr);
- }
- #endif
- return ret;
- }
- write_to_log = __write_to_log_daemon;
- }
- #if !defined(_WIN32)
- pthread_mutex_unlock(&log_init_lock);
- #endif
- return write_to_log(log_id, vec, nr);
- }
- static int __write_to_log_null(log_id_t log_fd __unused, struct iovec *vec __unused,
- size_t nr __unused)
- {
- return -1;
- }
- static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr)
- {
- ssize_t ret;
- int log_fd;
- if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) {
- if (log_id == LOG_ID_CRASH) {
- log_id = LOG_ID_MAIN;
- }
- log_fd = log_fds_kernel[(int)log_id];
- } else {
- return -EBADF;
- }
- do {
- ret = log_writev(log_fd, vec, nr);
- if (ret < 0) {
- ret = -errno;
- }
- } while (ret == -EINTR);
- return ret;
- }
- static int __write_to_log_init_kernel(log_id_t log_id, struct iovec *vec, size_t nr)
- {
- pthread_mutex_lock(&log_init_lock);
- if (write_to_log == __write_to_log_init) {
- log_fds_kernel[LOG_ID_MAIN] = log_open("/dev/"LOGGER_LOG_MAIN, O_WRONLY);
- log_fds_kernel[LOG_ID_RADIO] = log_open("/dev/"LOGGER_LOG_RADIO, O_WRONLY);
- log_fds_kernel[LOG_ID_EVENTS] = log_open("/dev/"LOGGER_LOG_EVENTS, O_WRONLY);
- log_fds_kernel[LOG_ID_SYSTEM] = log_open("/dev/"LOGGER_LOG_SYSTEM, O_WRONLY);
- write_to_log = __write_to_log_kernel;
- if (log_fds_kernel[LOG_ID_MAIN] < 0 || log_fds_kernel[LOG_ID_RADIO] < 0 ||
- log_fds_kernel[LOG_ID_EVENTS] < 0) {
- log_close(log_fds_kernel[LOG_ID_MAIN]);
- log_close(log_fds_kernel[LOG_ID_RADIO]);
- log_close(log_fds_kernel[LOG_ID_EVENTS]);
- log_fds_kernel[LOG_ID_MAIN] = -1;
- log_fds_kernel[LOG_ID_RADIO] = -1;
- log_fds_kernel[LOG_ID_EVENTS] = -1;
- write_to_log = __write_to_log_null;
- }
- if (log_fds_kernel[LOG_ID_SYSTEM] < 0) {
- log_fds_kernel[LOG_ID_SYSTEM] = log_fds_kernel[LOG_ID_MAIN];
- }
- }
- pthread_mutex_unlock(&log_init_lock);
- return write_to_log(log_id, vec, nr);
- }
- static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) {
- #if (FAKE_LOG_DEVICE == 0)
- int fd;
- fd = open("system/etc/disable_logd", O_RDONLY);//是否有disable_logd文件
- if (fd > 0) {
- use_logd = 0;
- close(fd);
- }
- #endif
- if(use_logd) {
- return __write_to_log_init_logd(log_id, vec, nr);
- } else {
- return __write_to_log_init_kernel(log_id, vec, nr);
- }
- }
- int __android_log_write(int prio, const char *tag, const char *msg)
- {
- return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
- }
- int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
- {
- struct iovec vec[3];
- char tmp_tag[32];
- if (!tag)
- tag = "";
- /* XXX: This needs to go! */
- if ((bufID != LOG_ID_RADIO) &&
- (!strcmp(tag, "HTC_RIL") ||
- !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
- !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
- !strcmp(tag, "AT") ||
- !strcmp(tag, "GSM") ||
- !strcmp(tag, "STK") ||
- !strcmp(tag, "CDMA") ||
- !strcmp(tag, "PHONE") ||
- !strcmp(tag, "SMS"))) {
- bufID = LOG_ID_RADIO;
- /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
- snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
- tag = tmp_tag;
- }
- #if __BIONIC__
- if (prio == ANDROID_LOG_FATAL) {
- android_set_abort_message(msg);
- }
- #endif
- vec[0].iov_base = (unsigned char *) &prio;
- vec[0].iov_len = 1;
- vec[1].iov_base = (void *) tag;
- vec[1].iov_len = strlen(tag) + 1;
- vec[2].iov_base = (void *) msg;
- vec[2].iov_len = strlen(msg) + 1;
- return write_to_log(bufID, vec, 3);
- }
- int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap)
- {
- char buf[LOG_BUF_SIZE];
- vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
- return __android_log_write(prio, tag, buf);
- }
- int __android_log_print(int prio, const char *tag, const char *fmt, ...)
- {
- va_list ap;
- char buf[LOG_BUF_SIZE];
- va_start(ap, fmt);
- vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
- va_end(ap);
- return __android_log_write(prio, tag, buf);
- }
- int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...)
- {
- va_list ap;
- char buf[LOG_BUF_SIZE];
- va_start(ap, fmt);
- vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
- va_end(ap);
- return __android_log_buf_write(bufID, prio, tag, buf);
- }
- void __android_log_assert(const char *cond, const char *tag,
- const char *fmt, ...)
- {
- char buf[LOG_BUF_SIZE];
- if (fmt) {
- va_list ap;
- va_start(ap, fmt);
- vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
- va_end(ap);
- } else {
- /* Msg not provided, log condition. N.B. Do not use cond directly as
- * format string as it could contain spurious '%' syntax (e.g.
- * "%d" in "blocks%devs == 0").
- */
- if (cond)
- snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
- else
- strcpy(buf, "Unspecified assertion failed");
- }
- __android_log_write(ANDROID_LOG_FATAL, tag, buf);
- abort(); /* abort so we have a chance to debug the situation */
- /* NOTREACHED */
- }
- int __android_log_bwrite(int32_t tag, const void *payload, size_t len)
- {
- struct iovec vec[2];
- vec[0].iov_base = &tag;
- vec[0].iov_len = sizeof(tag);
- vec[1].iov_base = (void*)payload;
- vec[1].iov_len = len;
- return write_to_log(LOG_ID_EVENTS, vec, 2);
- }
- /*
- * Like __android_log_bwrite, but takes the type as well. Doesn't work
- * for the general case where we're generating lists of stuff, but very
- * handy if we just want to dump an integer into the log.
- */
- int __android_log_btwrite(int32_t tag, char type, const void *payload,
- size_t len)
- {
- struct iovec vec[3];
- vec[0].iov_base = &tag;
- vec[0].iov_len = sizeof(tag);
- vec[1].iov_base = &type;
- vec[1].iov_len = sizeof(type);
- vec[2].iov_base = (void*)payload;
- vec[2].iov_len = len;
- return write_to_log(LOG_ID_EVENTS, vec, 3);
- }
- /*
- * Like __android_log_bwrite, but used for writing strings to the
- * event log.
- */
- int __android_log_bswrite(int32_t tag, const char *payload)
- {
- struct iovec vec[4];
- char type = EVENT_TYPE_STRING;
- uint32_t len = strlen(payload);
- vec[0].iov_base = &tag;
- vec[0].iov_len = sizeof(tag);
- vec[1].iov_base = &type;
- vec[1].iov_len = sizeof(type);
- vec[2].iov_base = &len;
- vec[2].iov_len = sizeof(len);
- vec[3].iov_base = (void*)payload;
- vec[3].iov_len = len;
- return write_to_log(LOG_ID_EVENTS, vec, 4);
- }
另外一个就是log_read_common.c文件,将log_read.c和log_read_kern.c合并。这样文件稍微复杂一点,因为在log_read.c和log_read_kern.c中都使用了struct logger_list 和struct logger结构体而且不一样,这样我们将共同部分做了一个基类的struct logger_list 和struct logger结构体。而在合并文件中定义了struct logger_list_logd struct logger_list_kernel结构体,将其基类放在第一个变量base中。而使用指针时,对外返回的指针强制转成基类,进入的指针强制转到相关的子类。因为基类的数据结构在子类结构体中是第一个,因此子类指针强转成父类,也是能正确调用到父类的变量的。
还有我们也是用use_logd这个全局变量来控制log机制的,并且定义了一个对外的函数set_uselogd. 因为使用read这块是在logcat进程中使用的,我们需要在logcat中调用。
- /*
- ** Copyright 2013-2014, 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.
- ** You may obtain a copy of the License at
- **
- ** http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing, software
- ** distributed under the License is distributed on an "AS IS" BASIS,
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
- #define _GNU_SOURCE /* asprintf for x86 host */
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define NOMINMAX /* for windows to suppress definition of min in stdlib.h */
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define __LOGGERIO 0xAE
- #define LOGGER_GET_LOG_BUF_SIZE _IO(__LOGGERIO, 1) /* size of log */
- #define LOGGER_GET_LOG_LEN _IO(__LOGGERIO, 2) /* used log len */
- #define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */
- #define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */
- #define LOGGER_GET_VERSION _IO(__LOGGERIO, 5) /* abi version */
- #define LOGGER_SET_VERSION _IO(__LOGGERIO, 6) /* abi version */
- #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
- static int8_t use_logd = 1;//版本控制
- void set_uselogd(int8_t uselogd) {//对外函数
- use_logd = uselogd;
- }
- /* 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
- #include
- #include
- #include
- /* 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); \
- logger = node_to_item((logger)->node.next, struct logger, node))
- #ifndef __unused
- #define __unused __attribute__((unused))
- #endif
- /* In the future, we would like to make this list extensible */
- static const char *LOG_NAME[LOG_ID_MAX] = {
- [LOG_ID_MAIN] = "main",
- [LOG_ID_RADIO] = "radio",
- [LOG_ID_EVENTS] = "events",
- [LOG_ID_SYSTEM] = "system",
- [LOG_ID_CRASH] = "crash",
- [LOG_ID_KERNEL] = "kernel",
- };
- const char *android_log_id_to_name(log_id_t log_id)
- {
- if (log_id >= LOG_ID_MAX) {
- log_id = LOG_ID_MAIN;
- }
- return LOG_NAME[log_id];
- }
- static int accessmode(int mode)
- {
- if ((mode & ANDROID_LOG_ACCMODE) == ANDROID_LOG_WRONLY) {
- return W_OK;
- }
- if ((mode & ANDROID_LOG_ACCMODE) == ANDROID_LOG_RDWR) {
- return R_OK | W_OK;
- }
- return R_OK;
- }
- /* repeated fragment */
更多相关文章
- 一款常用的 Squid 日志分析工具
- GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
- RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
- Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
- android 资源文件的使用说明
- Android(安卓)Studio中JNI程序的单步调试和日志打印
- Android实践--apk反编译
- 详解Android使用OKHttp3实现下载(断点续传、显示进度)
- Android如何开机自动执行脚本文件