0
点赞
收藏
分享

微信扫一扫

android N dmesg源码分析


dmesg源码位置:


external/toybox/toys/lsb/dmesg.c


system/core/toolbox/dmesg.c(应该不是这个)



在external/toybox/Android.mk的ALL_TOOLS变量中添加了dmesg.c,编译出的/system/bin/dmesg其实是一个指向


/system/bin/toybox的符号链接,


toybox是android m上集成的项目,目的在于用一个单一bin文件统一linux下的常用命令


Toybox combines many common Linux command line utilities together into a single BSD-licensed executable. It's simple, small, fast, and reasonably standards-compliant (POSIX-2008 and LSB 4.1).

Toybox's main goal is to make Android self-hosting by improving Android's command line utilities so it can build an installable Android Open Source Project image entirely from source under a stock Android system. After a talk at the 2013 Embedded Linux Conference explaining this plan (outlinevideo), Google merged toybox into AOSP and began shipping toybox in Android Mashmallow.


adb shell后执行的ls cat等命令也其实都指向toybox



linux内核自3.5以后提供了/dev/kmsg,用于向用户空间提供访问内核log的借口,


https://www.kernel.org/doc/Documentation/ABI/testing/dev-kmsg


What: /dev/kmsgDate: Mai 2012KernelVersion: 3.5Contact: Kay Sievers <kay@vrfy.org>Description: The /dev/kmsg character device node provides userspace accessto the kernel's printk buffer.


external/toybox/toys/lsb/dmesg.c: 

 
/* dmesg.c - display/control kernel ring buffer.
 
  
 *
 
  
 * Copyright 2006, 2007 Rob Landley <rob@landley.net>
 
  
 *
 
  
 *  
 http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/dmesg.html 

 
 
 
// We care that FLAG_c is 1, so keep c at the end.
 
USE_DMESG(NEWTOY(dmesg, "w(follow)Ctrs#<1n#c[!tr]", TOYFLAG_BIN))
 
 
 
config DMESG
 
   
 bool "dmesg"
 
   
 default y
 
   
 help
 
     
 usage: dmesg [-Cc] [-r|-t] [-n LEVEL] [-s SIZE] [-w]
 
 
 
     
 Print or control the kernel ring buffer.
 
 
 
     
 -C  Clear ring buffer without printing
 
     
 -c  Clear ring buffer after printing
 
     
 -n  Set kernel logging LEVEL (1-9)
 
     
 -r  Raw output (with <level markers>)
 
     
 -s  Show the last SIZE many bytes
 
     
 -t  Don't print kernel's timestamps
 
     
 -w  Keep waiting for more output (aka --follow)
 
*/
 
 
 
#define FOR_dmesg
 
#include "toys.h"
 
#include <sys/klog.h>
 
 
 
GLOBALS(
 
   
 long 
   
 level;
 
   
 long 
   
 size;
 
 
 
   
 int 
   
 color;
 
)
 
 
 
static 
   
 int 
   
 xklogctl( 
 int 
   
 type,  
 char 
   
 *buf,  
 int 
   
 len)
 
{
 
   
 int 
   
 rc = klogctl(type, buf, len);
 
 
 
   
 if 
   
 (rc<0) perror_exit( 
 "klogctl" 
 );
 
 
 
   
 return 
   
 rc;
 
}
 
 
 
// Use klogctl for reading if we're on a pre-3.5 kernel.
 
legacy_mode中调用klogct去读kmsg 

 
static 
   
 void 
   
 legacy_mode() {
 
   
 char 
   
 *data, *to, *from;
 
   
 int 
   
 size;
 
 
 
   
 // Figure out how much data we need, and fetch it.
 
   
 if 
   
 (!(size = TT.size)) size = xklogctl(10, 0, 0);
 
   
 data = to = from = xmalloc(size+1);
 
   
 data[size = xklogctl(3 + (toys.optflags & FLAG_c), data, size)] = 0;
 
 
 
   
 // Filter out level markers and optionally time markers
 
   
 if 
   
 (!(toys.optflags & FLAG_r))  
 while 
   
 ((from - data) < size) {
 
     
 if 
   
 (from == data || from[-1] ==  
 '\n' 
 ) {
 
       
 char 
   
 *to;
 
 
 
       
 if 
   
 (*from ==  
 '<' 
   
 && (to =  
 strchr 
 (from,  
 '>' 
 ))) from = ++to;
 
       
 if 
   
 ((toys.optflags&FLAG_t) && *from ==  
 '[' 
   
 && (to =  
 strchr 
 (from,  
 ']' 
 )))
 
         
 from = to+1+(to[1]== 
 ' ' 
 );
 
     
 }
 
     
 *(to++) = *(from++);
 
   
 }  
 else 
   
 to = data+size;
 
 
 
   
 // Write result. The odds of somebody requesting a buffer of size 3 and
 
   
 // getting "<1>" are remote, but don't segfault if they do.
 
   
 if 
   
 (to != data) {
 
//将/proc/kmsg中的内容写到标准输出中,这句完成将kmsg输出的任务
 
    
   
 xwrite(1, data, to-data);
 
     
 if 
   
 (to[-1] !=  
 '\n' 
 ) xputc( 
 '\n' 
 );
 
   
 }
 
   
 if 
   
 (CFG_TOYBOX_FREE)  
 free 
 (data);
 
}
 
 
 
static 
   
 void 
   
 color( 
 int 
   
 c) {
 
   
 if 
   
 (TT.color)  
 printf 
 ( 
 "\033[%dm" 
 , c);
 
}
 
 
 
void 
   
 dmesg_main( 
 void 
 )
 
{
 
   
 // For -n just tell kernel which messages to keep.
 
   
 if 
   
 (toys.optflags & FLAG_n) {
 
     
 xklogctl(8, 0, TT.level);
 
 
 
     
 return 
 ;
 
   
 }
 
 
 
   
 // For -C just tell kernel to throw everything out.
 
   
 if 
   
 (toys.optflags & FLAG_C) {
 
     
 xklogctl(5, 0, 0);
 
 
 
     
 return 
 ;
 
   
 }
 
 
 
   
 TT.color = isatty(1);
 
 
 
   
 //  
 http://kernel.org/doc/Documentation/ABI/testing/dev-kmsg 

 
 
 
   
 // Each read returns one message. By default, we block when there are no
 
   
 // more messages (--follow); O_NONBLOCK is needed for for usual behavior.
 
// dmesg命令在3.5内核之后读取的是 
 /dev/kmsg
 
   
 int 
   
 fd = xopen( 
 "/dev/kmsg" 
 , O_RDONLY | ((toys.optflags&FLAG_w)?0:O_NONBLOCK));
 
   
 while 
   
 (1) {
 
     
 char 
   
 msg[8192];  
 // CONSOLE_EXT_LOG_MAX.
 
     
 unsigned  
 long 
   
 long 
   
 time_us;
 
     
 int 
   
 facpri, subsystem, pos;
 
     
 char 
   
 *p, *text;
 
     
 ssize_t len;
 
 
 
     
 // kmsg fails with EPIPE if we try to read while the buffer moves under
 
     
 // us; the next read will succeed and return the next available entry.
 
     
 do 
   
 {
 
       
 len = read(fd, msg,  
 sizeof 
 (msg));
 
     
 }  
 while 
   
 (len == -1 &&  
 errno 
   
 == EPIPE);
 
     
 // All reads from kmsg fail if you're on a pre-3.5 kernel.
 
     
 if 
   
 (len == -1 &&  
 errno 
   
 == EINVAL) {
 
       
 close(fd);
 
       
 return 
   
 legacy_mode 
 ();//3.5之前内核还是在 
 legacy_mode中调用klogct去读kmsg 

 
     
 }
 
     
 if 
   
 (len <= 0)  
 break 
 ;
 
  
 //msg中保存的是从/dev/kmsg中读到的原始字符串,eg
 
//4,222,12150,-;ACPI: 4 ACPI AML tables successfully acquired and loaded 

 
     
 msg[len] = 0;
 
 
 
 
 // 用sscanf解析msg
 

  // char *msg = "4,222,12150,-;ACPI: 4 ACPI AML tables successfully acquired and loaded"; 

 

  // int retval = sscanf(msg, "%u,%*u,%llu,%*[^;];%n", &facpri, &time_us, &pos); 

 

  // %u, 对应优先级"4,",因此输出facpri--4 

 

  // %*u, 跳过行数"222," 

 

  // %llu,对应时间"12150," 下来剩下的就到了"-;ACPI: 4 ACPI AML tables successfully acquired and loaded"; 

 

  //%*[^;]; 这个意义是跳过接下来从不是字符;开始的到字符; 也就是会跳过"-;",剩下就到了"ACPI: 4 ACP。。。。",这些//就是真正的log 

 

  //对于%n,gnu c 实现了 C 标准的 format specify 的 %n,它的含义是返回从该次 XXscanf 调用开始到此读了多少个字节,//目前已经读取到了"ACPI...", 

 

  //从4到A前面的;一共14个字符,A是第15个,因此%n将使pos获取14 

 

  //整个sscanf匹配到的输入项只有facpri和time_us,pos不算在内,因此返回值才与2做比较 

 

  //获取到了pos后,text = msg + pos的意义就很明确了,从原始的msg中提取出";"后面真正的文本,作为text 

 

  //这里text就是ACPI: 4 ACPI AML tables successfully acquired and loaded

http://kernel.org/doc/Documentation/ABI/testing/dev-kmsg



这个文档上也对/dev/kmsg的标准格式有所说明:

if    
 ( 
 sscanf  (msg,  
 "%u,%*u,%llu,%*[^;];%n" 
 , &facpri, &time_us, &pos) != 2)
 
        continue  ;
 
 
 
      // Drop extras after end of message text.
 
      text = msg + pos;
 
      if    
 ((p =  
 strchr  (text,  
 '\n' 
 ))) *p = 0;
 
 
 
//   subsystem 
 是指kkernel log中带有 子系统名:详细信息的log,比如
 
// 
 
//usb usb2: New USB device found, idVendor=1d6b, idProduct=0002 

 
      // Is there a subsystem? (The ": " is just a convention.)
 
      p =  
 strstr  (text,  
 ": " 
 );
 
      subsystem = p ? (p - text) : 0;
 
 
 
      // "Raw" is a lie for /dev/kmsg. In practice, it just means we show the
 
      // syslog facility/priority at the start of each line.
 
// 打印优先级
 
      if    
 (toys.optflags&FLAG_r)  
 printf  ( 
 "<%d>" 
 , facpri);
 
 
 
      if    
 (!(toys.optflags&FLAG_t)) {
 
        color(32); //调用printf("\033[%dm", 32); 用绿色打印 

 
// 如果不带-t参数就打印时间戳
 
        printf  ( 
 "[%5lld.%06lld] " 
 , time_us/1000000, time_us%1000000);
 
        color(0);
 
      }
 
 
 
      // Errors (or worse) are shown in red, subsystems are shown in yellow.
 
// 1 时间戳之后如果有subsystem先打印subsystem
 
      if    
 (subsystem) {
 
        color(33); // 调用printf("\033[%dm", 32); 用黄色打印 

 
        printf  ( 
 "%.*s" 
 , subsystem, text);
 
        text += subsystem;
 
        color(0);
 
      }
 
// 2 下来按优先级,4级及以上调用xputs输出,1-3级用printf红色输出
 
      if    
 (!((facpri&7) <= 3)) xputs(text);
 
      else    
 {
 
        color(31);
 
        printf  ( 
 "%s" 
 , text);
 
        color(0);
 
        xputc( 
 '\n' 
 );
 
      }
 
    }
 
  close(fd);
}

举报

相关推荐

0 条评论