• 在我们开发过程中,内核的信息一开机就会很多,然后一直打个不停,很烦人,也...1、在kernel中修改log默认等级,kernel-3.18/include/linux/printk.h static inline void console_verbose(void)函数中的 console_logle

    在我们开发过程中,内核的信息一开机就会很多,然后一直打个不停,很烦人,也不好看调试信息,更不好在串口终端输入相关的命令进行调试。

    那么有什么办法可以解决?

    1、在kernel中修改log默认等级,

    kernel-3.18/include/linux/printk.h
             static inline void console_verbose(void)函数中的
        console_loglevel = CONSOLE_LOGLEVEL_MIN; //CONSOLE_LOGLEVEL_MOTORMOUTH;
    然后重新编译内核。


    2、通过以下方法可以修改串口的用户等级,可以自主决定使用串口log的级别,仅限调试。
           2.1 修改vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt8127/rules.mk
                SELINUX_STATUS := 2
          2.2 system/core/rootdir/init.rc b/system/core/rootdir/init.rc
          service console /system/bin/sh
            class core
             console
             disabled
          //user shell
         seclabel u:r:shell:s0
      
         2.3 此时的串口为root用户,然后通过echo 0 > /proc/sys/kernel/printk  关闭串口或者打开。
          需要重新编译 lk ,boot。

    展开全文
  • Android 关闭Log日志

    2016-05-19 17:23:10
    平时我们在开发Android应用时,会经常使用android.utils.Log类来打印日志。但到发布时,往往我们希望关闭Log输出。总不能一条条去注释去删除吧。下面推荐2个办法 直接点的,就是重新封装个Log类。然后设个开关。...

    平时我们在开发Android应用时,会经常使用android.utils.Log类来打印日志。但到发布时,往往我们希望关闭Log输出。总不能一条条去注释去删除吧。下面推荐2个办法


    直接点的,就是重新封装个Log类。然后设个开关。

    [java] view plain copy
    1. public class MyLog{  
    2.         public static final DEBUG = false;  
    3.   
    4.         public static void d(..){  
    5.             if(DEBUG) Log.d(..)  
    6.         }  
    7.   
    8.         public static void v(..){  
    9.             if(DEBUG) Log.v(..)  
    10.             }  
    11.         }  


    还有种方法,利用ProGuard,直接在混淆代码的时候把Log代码删除。

    -assumenosideeffects class android.util.Log {
        public static *** d(...);
        public static *** v(...);
        public static *** i(...);
    }





    
    这样子打包的时候,Log.d/v/i 的代码都不会打包进去。
    
    展开全文
  • Kernel Log

    2020-04-07 16:20:05
    在开发Linux device Driver或者跟踪调试内核行为的时候经常要通过Log API来trace整个过程,Kernel API printk() 是整个Kernel Log机制的基础API,几乎所有的Log方式都是基于printk来实现的。 利用printk,我们可以...

    在开发Linux device Driver或者跟踪调试内核行为的时候经常要通过Log API来trace整个过程,Kernel API printk() 是整个Kernel Log机制的基础API,几乎所有的Log方式都是基于printk来实现的。

    利用printk,我们可以像开发C应用中printf接口一样印log,最简单的方式,我们只要把需要打印的内容传给printk函数就可以了,如下:

    printk("This is just an example!!");

    当然使用printk还有一些需要注意的地方,在详细讲述之前我们先分析一下printk()实现,其流程大致如下图所示:

     

    从上图可以看出,printk的流程大致可以分为两步:
    1. 将所有Log输出到内核的Log buffer,该Log Buffer是一个循环缓冲区,其地址可以在内核中用log_buf变量访问。
    2. 根据设定的Log级别决定是否将Log输出到Console。

    所以我们打印的log会走向两个位置:

    1. Log Buffer,该Buffer的内容可以在user space通过/proc/kmsg来访问。
    2. Console,Console的实现可以有很多,目前我们用到的有UART Console和RAM Console。拿UART Console来说,通向UART Console的log会在对应的UART端口打印出来。而RAM Console也是我们一种重要的Debug手段。

    对于console log,不可避免的对系统的性能有损失,尤其是像UART Log这种收到硬件传输效率影响的。所以对于console log设置了两道关卡。第一个是对Log级别进行过滤,只能输出高优先级的log;第二个是为UART Console设置单独的开关,在不必要的时候可以将其关闭以提高系统性能。

    在这里我们提到了Log Level的概念,那什么是Log Level呢?

    LOG 优先级

    Log Level,也叫做Log优先级,为了能够区分各个Log的重要程度,printk机制设计了若干Log级别以作区分。当我们读取log buffer (adb shell cat /proc/kmsg)的时候可以看到如下的log,在每一行Log的前面有一对尖角号,里面包含一个数字,这个数字即为这行Log优先级。

    <6>[  641.908202] (0)[130:healthd]healthd: battery l=26 l2=50 v=3859 t=30.0 h=2
    <4>[  641.908685] (0)[64:bat_thread_kthr][0x4]=0x9b [0x5]=0x4 [0x6]=0x70
    <6>[  641.914564] (0)[130:healthd]healthd: battery l=26 l2=50 v=3859 t=30.0 h=2
    <4>[  643.716514] (0)[0:swapper/0][printk_delayed:start]
    <4>[  643.717113] (0)[0:swapper/0][WDK], local_bit:0x0, cpu:0,RT[643706704575]
    <4>[  643.717120] (0)[0:swapper/0][WDK], local_bit:0x1, cpu:0, check bit0x:1,RT[6
    <4>[  643.717127] (0)[0:swapper/0][WDK]: kick Ex WDT,RT[643706714498]
    <4>[  643.717134] (0)[0:swapper/0][thread:86][RT:643706722652] 2013-01-01 00
    <4>[  643.721143] (0)[0:swapper/0][printk_delayed:done]
    <7>[  644.916496] (0)[0:swapper/0][ccci/ctl] (1)get_txpower(0): 16
    <7>[  644.916520] (0)[0:swapper/0][ccci/ctl] (1)get_txpower(1): 16
    <7>[  644.916540] (0)[0:swapper/0][ccci/ctl] (1)get_txpower(2): 16
    <6>[  644.916663] (0)[96:flush-179:0][BLOCK_TAG] BDI_Flush statistic in timeline
    <6>[  644.916682] (0)[96:flush-179:0][BLOCK_TAG] BDI_Flush [(PID):cnt] -- (  96

    完整的8个级别的定义可以参考下表,值越小级别越高:

     

    宏定义
    级别
    描述
    KERN_EMERG
    "<0>"
    紧急信息,此信息会引起系统崩溃
    KERN_ALERT
    "<1>"
    提示要马上采取某些行动
    KERN_CRIT
    "<2>"
    关键信息,通常有严重的软件或者硬件问题发生了
    KERN_ERR
    "<3>"
    通常用来报告错误,例如设备驱动通常会用来报告硬件操作失败等
    KERN_WARNING
    "<4>"
    警告信息,用来警告那些并不会造成严重的系统异常的问题
    KERN_NOTICE
    "<5>"
    用于正常但是值得注意的情况,比如大量安全相关的log
    KERN_INFO
    "<6>"
    信息,许多驱动程序都会在硬件启动的时候使用这个级别打印Log
    KERN_DEBUG
    "<7>"
    用于调试信息的打印

     

    那优先级是怎么应用的呢?

    我们可以为将要打印的log指定优先级,举例如下,可以在我们要打印的log前面简单的添加上Log优先级的宏定义即可,这个优先级在printk API里面会去解析处理,以判断是否要打印到console中去。

    printk(KERN_ERR"This is an error message!!");

    如果不指定优先级会怎样呢?

    如果在印Log的时候不指定Log的优先级,printk会为这行Log采用默认的优先级。通常系统默认的优先级是4,即warning级别。

    系统默认的优先级可以通过读取/proc文件来得到,如下所示,其中读回来的第2个参数即为未指定Log Level的时候printk默认的Log级别。

    D:\>adb shell cat /proc/sys/kernel/printk
    6       4       1       6                

    /proc/sys/kernel/printk里面的参数意义是什么?

    前面我们使用cat读取了/proc/sys/kernel/printk里面的内容,读取的这4个数字的含义分别是:

    1. 第一个参数表示console log level,即只有优先级大于这个级别的Log才可以打印到Console。
    2. 第二个参数表示默认Log级别,即打印Log未明确指定Log level的时候默认采用的Log级别。
    3. 第三个参数表示最小可用的Log Level,用于do_syslog()系统调用。
    4. 第四个参数表示默认的Console Log Level,未找到使用的地方。

    Console Log 输出控制

    从前面的图例以及讲述都有提到,console_loglevel 决定了哪些级别的log可以输出到console。而console_loglevel的值可以通过 /proc/sys/kernel/printk 来读取出来。

    除此之外,我们还可以通过/proc/sys/kernel/printk设置console_loglevel来达到控制 console log 输出的目的,方法如下(修改这个参数需要有root权限):

    D:\>adb shell cat /proc/sys/kernel/printk        
    6       4       1       6                        
    D:\>adb shell "echo 8 > /proc/sys/kernel/printk" 
    D:\>adb shell cat /proc/sys/kernel/printk        
    8       4       1       6                        

    上面黄色一行命令将console_loglevel设置8,即所有级别的log(因为定义的最低优先级的Log Level是7)都可以输出到console。当然通过这个命令也可以禁止一些低优先级的log输出到console,只要将console_loglevel的值设置小一些即可。

    UART Console 的控制

    对于UART Console单独设置了开关主要是因为其对系统性能的影响比较大,因为UART Console是同步的方式通过硬件以固定的传输速率印Log,如果Log量比较大的时候,印Log不可避免会花费系统较多的时间,这样就会引起较多的Performance问题,如UI卡顿等。另外由于往UART Console印Log会关闭中断,严重的时候可能会引起系统无法响应或者重启。

    也正因为此,我们在user版本上面默认是关闭UART Console Log的。

    那么如何在runtime控制UART Console 的打开和关闭呢?可以使用如下命令(执行该命令需要有root权限):

    D:\>adb shell "echo 1 > /sys/module/printk/parameters/disable_uart"  
    D:\>adb shell "echo 0 > /sys/module/printk/parameters/disable_uart"  

    通过将disable_uart参数设置为1来关闭UART Console,反之通过将disable_uart参数设置为0来打开UART Console。

    展开全文
  • 以下两种方式是一样的,可以查看内核中binder,logger模块打印的log。1. emulator -avd eclipseAvd -kernel ../kernel_2.6.25/arch/arm/boot/zImage -show-kernel &2. adb shellcat /proc/kmsg

    1. emulator对应的cpu的名称是goldfish

    2. 以下两种方式是一样的,可以查看内核中binder,logger模块打印的log。

    a. emulator -avd eclipseAvd -kernel ../kernel_2.6.25/arch/arm/boot/zImage -show-kernel &

     

    b. adb shell

    cat /proc/kmsg

    展开全文
  • 在分析Android7.0 init进程一文中提到,在init进程中是通过klog来输出log信息的,但是由于log的级别不同可能导致有些添加的log无法输出来。在init .cpp的main函数中初始化klog。 klog_init(); //初始化klog klog_...

        在分析Android7.0 init进程一文中提到,在init进程中是通过klog来输出log信息的,但是由于log的级别不同可能导致有些添加的log无法输出来。在init .cpp的main函数中初始化klog。

        klog_init();          //初始化klog
        klog_set_level(KLOG_NOTICE_LEVEL);   //设置klog的级别为NOTICE
    
    system/core/libcutils/klog.c

    void klog_init(void) {
        if (klog_fd >= 0) return; /* Already initialized */      //klog_fd默认值为-1,如果大于等于1表示klog已经初始化过,返回
    
        klog_fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC);   //打开/dev/kmsg文件,获得文件描述符
        if (klog_fd >= 0) {                      //大于等于0表示,打开成功,init进程的log都会输出到kernel log中
            return;  
        }
    
        static const char* name = "/dev/__kmsg__"; 
        if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) {   //如果上面没有打开成功,创建/dev/_kmsg_文件
            klog_fd = open(name, O_WRONLY | O_CLOEXEC);      //打开文件,获取文件描述符
            unlink(name);
        }
    }
    void klog_set_level(int level) {
        klog_level = level;                  //将设置的level赋值给klog_level
    }

    在init.cpp通过NOTICE函数输出log信息。但是INFO函数就输不出log,下面我们看一下具体原因。

        NOTICE("init %s started!\n", is_first_stage ? "first stage" : "second stage");
    
    在system/core/init/log.h头文件中对NOTICE,INFO等函数进行定义

    #define ERROR(x...)   init_klog_write(KLOG_ERROR_LEVEL, x)
    #define WARNING(x...) init_klog_write(KLOG_WARNING_LEVEL, x)
    #define NOTICE(x...)  init_klog_write(KLOG_NOTICE_LEVEL, x)
    #define INFO(x...)    init_klog_write(KLOG_INFO_LEVEL, x)
    #define DEBUG(x...)   init_klog_write(KLOG_DEBUG_LEVEL, x)
    #define VERBOSE(x...) init_klog_write(KLOG_DEBUG_LEVEL, x)
    调用NOTICE函数,也就调到了函数init_klog_wirte传入的参数为NOTICE log level,如果调用别的函数就传入对应的log level。还有传入需要打印的信息。

    先看一下各个log level的值,代码定义位置system/core//include/cutils/klog.h

    #define KLOG_ERROR_LEVEL   3
    #define KLOG_WARNING_LEVEL 4
    #define KLOG_NOTICE_LEVEL  5
    #define KLOG_INFO_LEVEL    6
    #define KLOG_DEBUG_LEVEL   7

    继续分析代码system/core/init/log.cpp

    void init_klog_write(int level, const char* fmt, ...) {
        va_list ap;
        va_start(ap, fmt);
        init_klog_vwrite(level, fmt, ap);        //函数调用
        va_end(ap);
    }
    
    static void init_klog_vwrite(int level, const char* fmt, va_list ap) {
        static const char* tag = basename(getprogname());
    
        if (level > klog_get_level()) return;      //之前设置的level为NOTICE 5,现在level也为5相等为false,INFO level为6所以return
    
        // The kernel's printk buffer is only 1024 bytes.
        // TODO: should we automatically break up long lines into multiple lines?
        // Or we could log but with something like "..." at the end?
        char buf[1024];             //kernel 的printk buffer只有1024个字节, 将长的单行log,变为多行,或者直接省略掉
        size_t prefix_size = snprintf(buf, sizeof(buf), "<%d>%s: ", level, tag);
        size_t msg_size = vsnprintf(buf + prefix_size, sizeof(buf) - prefix_size, fmt, ap);
        if (msg_size >= sizeof(buf) - prefix_size) {
            msg_size = snprintf(buf + prefix_size, sizeof(buf) - prefix_size,
                                "(%zu-byte message too long for printk)\n", msg_size);
        }
    
        iovec iov[1];
        iov[0].iov_base = buf;
        iov[0].iov_len = prefix_size + msg_size;
    
        klog_writev(level, iov, 1);       //传送整理好的信息
    }
    system/core/libcutils/klog.c

    void klog_writev(int level, const struct iovec* iov, int iov_count) {
        if (level > klog_level) return;           //由于level与klog_level都为5,所以继续执行
        if (klog_fd < 0) klog_init();               //前面已经初始化过klog_fd大于等于0
        if (klog_fd < 0) return;                     
        TEMP_FAILURE_RETRY(writev(klog_fd, iov, iov_count));   
    }

    //system/core/include/log/uio.h
    extern int  readv( int  fd, struct iovec*  vecs, int  count );   //定义readv函数
    extern int  writev( int  fd, const struct iovec*  vecs, int  count );  /定义writev函数
    //system/core/liblog/uio.c
    #include <log/uio.h>
    LIBLOG_ABI_PUBLIC int writev(int fd, const struct iovec *vecs, int count)
    {
        int   total = 0;
    
        for ( ; count > 0; count--, vecs++ ) {
            const char*  buf = vecs->iov_base;
            int          len = vecs->iov_len;
    
            while (len > 0) {
                int  ret = write( fd, buf, len ); //调用linux的write函数,fd为/dev/kmsg的文件描述符,所以将log写入到kmsg中即kernel log中。
                if (ret < 0) {
                    if (total == 0)
                        total = -1;
                    goto Exit;
                }
                if (ret == 0)
                    goto Exit;
    
                total += ret;
                buf   += ret;
                len   -= ret;
            }
        }
    Exit:
        return total;
    }

        之前做项目时遇到一个问题,在开机过程中kernel 与 init进程中的log都输在kernel log中,而启动zygote之后log是输出在android中的,这样就发生了init进程到framework这段时间无法精确计算,对分析开机流程总耗时带来不小的困扰。所以我们就仿照klog自己定义TAG来输出信息,将android 中的log输出到kernel中,这样同一行log即在kernel log中有也在android log中有就可以精确计算时间了。

    首先在system/core/include/cutils/klog.h中定义log level

    	#define KLOG_PERFORMANCE_LEVEL 0              //根据之前分析,将level设置小一点,至少要小于5
    	#define KLOG_BOOTINFO(tag,x...) klog_write(KLOG_PERFORMANCE_LEVEL, "<0>" tag ": " x)    //定义函数关系

    定义完之后就可以在framework中使用了,

    例如init进程启动完zygote服务,会进入/frameowrk/base/cmds/app_process/app_main.cpp我们可以在这里使用

    #include <cutils/klog.h>              //先include对应的头文件
    #define BOOTINFO(x...) KLOG_BOOTINFO("bootinfo", x)       //定义对应的函数关系

     BOOTINFO("Entered app_main.cpp main() \n");    //就可以通过BOOTINFO函数将log输出到kernel log中
    不过将编译好的文件替换到手机中仍然无法输出对应log信息,经过分析发现是有与selinux权限,输出log存在selinux安全问题。

    为了调试我们本地只好将selinux关闭了,代码还是在init .cpp 中我们之前将init进程时有过提到。

    static void selinux_initialize(bool in_kernel_domain) {
        Timer t;
    
        //..............
        if (in_kernel_domain) {
           //.........
    
            bool kernel_enforcing = (security_getenforce() == 1);
            bool is_enforcing = selinux_is_enforcing();
            if (kernel_enforcing != is_enforcing) {
                if (security_setenforce(is_enforcing)) {     //可以直接将is_enforcing改为false,就将selinux关闭了
                    ERROR("security_setenforce(%s) failed: %s\n",
                          is_enforcing ? "true" : "false", strerror(errno));
                    security_failure();
                }
            }
    
            //.............
        } else {
            selinux_init_all_handles();
        }
    }
    展开全文
  • 最近在开机加一些自己的测试程序,编译的是eng版本,希望安卓开机后能够看到自己的调试信息,可是一开机就会有很多其它的信息干扰我的调试,那么如何屏蔽掉kernel的kmsg打印的这些信息呢?很简单,我们找到以下这个...
  • user版本打开uart 如何在user版本中使用串口(uart) bootable/bootloader/lk/app/mt_boot/mt_boot.c 582 #ifdef USER_BUILD 583 sprintf(cmdline,"%s%s",cmdline," printk.disable_uart=1");...
  • 方法一: 动态设置打印优先级,每次开机需要设置一次 su echo 0 > proc/sys/kernel/printk ...修改/kernel/printk/printk.c ...console_printk[0]原值为CONSOLE_LOGLEVEL_DEFAULT;... CONSOLE_LOGLEVEL_MIN, ...
  • 在user版本下,我们没有权限对/proc/kmsg进行操作,只有对拥有root权限或者system组的才能对其进行...1、在LINUX/android/device/qcom/common/rootdir/etc新建一个目录 $mkdir x.sh x.sh脚本内容如下: #!/bin/bas
  • echo 0 > /proc/sys/kernel/printk  --> 這個是把 kernel 關掉的方法....
  • 高通平台启动log概述(PBL log、sbl1 logkernel log) 在嵌入式linux的调试过程中log有着至关重要的地位,等同于医生的CT报告。能够熟悉启动各个阶段的log,如PBL阶段,sbl1阶段,kernel阶段,android阶段,对于...
  • 1.adb shell dmesg > d:\dmesg.log   1. Check Android system log $ adb logcat 2. Check the kernel log $ adb shell cat /proc/kmsg
  • 本文转自:... 高通平台启动log概述(PBL log、sbl1 logkernel log)在嵌入式linux的调试过程中log有着至关重要的地位,等同于医生的CT报告。能够熟悉启动各个阶段的log,如PBL阶段,sbl1阶段,kerne...
  • 主要介绍除了常规的kernel的printk和android的DDMS, logcat外的几个调试手段. 包括bugreport, oprofile, traceview, ftrace等. Bugreport Bugreport是An
1 2 3 4 5 ... 20
收藏数 5,585
精华内容 2,234