Logger详解(一)

本文编辑整理自: http://www.linuxidc.com/Linux/2011-07/38987.htm
一、简介
Android为我们提供了一个轻量级的日志系统,在用户空间分别提供了Java接口和C/C++接口来使用这个日志系统。
关于Android的日志系统,请先阅读《 Android中LOG机制详解》,《 在Android的c/c++域使用LOG》,《 logcat命令详解
Android日志系统最终还是以驱动程序的形式实现在内核空间的。Logger驱动程序主要由两个文件构成,分别是
       kernel/common/drivers/staging/Android/logger.h       
       kernel/common/drivers/staging/Android/logger.c
 本文将介绍Logger驱动程序的相关数据结构,然后对Logger驱动程序源代码进行情景分析,分别日志系统初始化情景、日志读取情景和日志写入情景。
二、基本数据结构
我们首先来看logger.h头文件的内容:
#ifndef _LINUX_LOGGER_H   
#define _LINUX_LOGGER_H   
  
#include <linux/types.h>   
#include <linux/ioctl.h>   
  
struct logger_entry {  
    __u16        len;     /* length of the payload */  
    __u16        __pad;   /* no matter what, we get 2 bytes of padding */  
    __s32        pid;     /* generating process's pid */  
    __s32        tid;     /* generating process's tid */  
    __s32        sec;     /* seconds since Epoch */  
    __s32        nsec;    /* nanoseconds */  
    char         msg[0]/* the entry's payload */  
};  
  
#define LOGGER_LOG_RADIO    "log_radio" /* radio-related messages */   
#define LOGGER_LOG_EVENTS   "log_events"    /* system/hardware events */   
#define LOGGER_LOG_SYSTEM "log_SYSTEM" /* system/framework  message*/
#define LOGGER_LOG_MAIN     "log_main"  /* everything else */   
  
#define  LOGGER_ENTRY_MAX_LEN        (4*1024)   
#define  LOGGER_ENTRY_MAX_PAYLOAD    \   
    (LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry))  
  
#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 */   
  
#endif /* _LINUX_LOGGER_H */  
logger_entry 是一个用于描述一条 Log 记录的结构体。 len 成员变量记录了这 条记录的有效负载的长度,有效负载指定的日志记录本身的长度,但是不包括用于描述这个记录的 struct logger_entry 结构体 。我们调用Android.util.Log接口来使用日志系统时,会指定日志的优先级别Priority、Tag字符串以及Msg字符串;Priority + Tag + Msg三者内容的长度加起来就是记录的有效负载长度了。 __pad 成员变量是用来对齐结构体的。 pid tid 成员变量分别用来标明是 哪条进程 哪个线程 写入的这条记录。 sec nsec 成员变量记录日志写的时间。 msg 成员变量记录的就有效负载的内容了,它的大小由 len 成员变量来确定。
       接着定义两个宏:
       #define  LOGGER_ENTRY_MAX_LEN              (4*1024)       
       #define  LOGGER_ENTRY_MAX_PAYLOAD    \                        
 (LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry))
从这两个宏可以看出,每条日志记录的有效负载长度加上结构体 logger_entry 的长度不能超过4K个字节。       
logger.h文件中还定义了其它宏,读者可以自己分析,在下面的分析中,碰到时,我们也会详细解释。再来看logger.c文件中,其它相关数据结构的定义:
/* 
 * struct logger_log - represents a specific log, such as 'main' or 'radio' 
 * 
 * This structure lives from module insertion until module removal, so it does 
 * not need additional reference counting. The structure is protected by the 
 * mutex 'mutex'. 
 */  
struct  logger_log {  
    unsigned char *      buffer/* the ring buffer itself */  
    struct miscdevice    misc;    /* misc device representing the log */  
    wait_queue_head_t    wq/* wait queue for readers */  
    struct list_head      readers/* this log's readers */  
    struct mutex         mutex /* mutex protecting buffer */  
    size_t           w_off;   /* current write head offset */  
    size_t           head;    /* new readers start here */  
    size_t           size;    /* size of the log */  
};  
  
/* 
 * struct logger_reader - a logging device open for reading 
 * 
 * This object lives from open to release, so we don't need additional 
 * reference counting. The structure is protected by log->mutex. 
 */  
struct  logger_reader {  
    struct logger_log *  log;     /* associated log */  
    struct list_head     list;    /* entry in logger_log's list */  
    size_t           r_off /* current read head offset */  
};  
/* logger_offset - returns index 'n' into the log via (optimized) modulus */  
#define  logger_offset(n)    ((n) & (log->size - 1))  

结构体 logger_log 就是真正用来保存日志的地方了。 buffer 成员变量变是用保存日志信息的内存缓冲区,它的大小由 size 成员变量确定。从 misc 成员变量可以看出, logger驱动程序使用的设备属于misc类型的设备,通过在Android模拟器上执行cat /proc/devices命令,可以看出,misc类型设备的 主设备号是10 wq 成员变量是 一个等待队列,用于保存正在等待读取日志的进程 readers 成员变量用来保存当前正在读取日志的进程,正在读取日志的进程由结构体 logger_reader 来描述。 mutex 成员变量是一个互斥量,用来保护log的并发访问。可以看出, 这里的日志系统的读写问题,其实是一个生产者-消费者的问题,因此,需要互斥量来保护log的并发访问 。  w_off 成员变量 用来记录下一条日志应该从哪里开始写 head 成员变量用来表示打开日志文件中,应该从哪一个位置开始读取日志。
    结构体 logger_reader 用来表示一个读取日志的进程, log 成员变量指向要读取的日志缓冲区。 list 成员变量用来连接其它读者进程。 r_off 成员变量 表示当前要读取的日志在缓冲区中的位置
        logger_log 结构体中用于保存日志信息的内存缓冲区 buffer 是一个循环使用的环形缓冲区,缓冲区中保存的内容是以结构体 logger_entry 为单位的,每个单位的组成为: logger_entry + priority + tag + msg
       由于是内存缓冲区buffer是一个循环使用的环形缓冲区,给定一个偏移值,它在buffer中的位置由下logger_offset来确定:
        #define logger_offset(n)          ((n) & (log->size - 1))
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Logger是一个Shell命令接口,可以通过该接口使用Syslog的系统日志模块,也可以从命令行直接向系统日志文件写入一行信息。Logger命令的语法是:logger [options [message,其中message是要写入日志文件的信息。可以使用选项来指定日志级别、标记和设施。使用Logger命令时可以通过-f选项将日志内容从文件中读取。Logger命令还可以通过-t选项设置标记,通过-p选项设置设施和级别来指定日志级别。例如,可以使用以下命令将一条日志消息写入系统日志文件:logger -i -t "my_test" -p local3.notice "test_info"[2。在这个例子中,-i选项表示忽略错误,-t选项设置标记为"my_test",-p选项设置设施和级别为local3.notice,"test_info"是要写入日志文件的消息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [linux日志logger命令详解](https://blog.csdn.net/u011630575/article/details/52055116)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Linux系统logger日志详解](https://blog.csdn.net/renfeigui0/article/details/101098496)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值