首页
社区
课程
招聘
玩转Android10源码开发定制(12)内核篇之logcat输出内核日志
发表于: 2021-1-7 22:10 10707

玩转Android10源码开发定制(12)内核篇之logcat输出内核日志

2021-1-7 22:10
10707

Android系统中日志信息分为内核空间日志信息和用户空间日志信息,查看用户空间的log直接用logcat就可以了。比如如下命令:

或者使用如下命令:

如果需要查看内核控件日志信息,有以下几种方式查看。

读取/proc/kmsg,命令如下

读取/proc/kmsg属于消费型读取,读取之后再次读取不会显示已经读取过的日志信息。

读取/dev/kmsg,命令如下

读取/dev/kmsg会显示缓存区里面的所有日志信息。新写入的日志信息会不断累加到日志缓冲器中。

使用dmesg命令读取

dmesg命令读取一次只显示一部分日志,非阻塞执行,从他的源码中分析他是读取/dev/调用klogctl方式读取。demsg源码实现方式如下。

实现代码路径位于源码目录:

external/toybox/toys/lsb/dmesg.c

在本文中将采用init.rc中注册后台服务kernellogd。kernellogd不断读取/proc/kmsg信息,然后写到用户层的日志系统的方式达到目的。
流程图如下:

kernellogd有两种方式集成到系统,一种是直接将源码放到系统某一个文件夹,创建Android.mk文件,加入到系统编译链中;另种方式使用android studio工具开发,使用cmake或者ndk将源码编译成二进制可执行文件。目前我采用了使用android studio开发的方式,编译为arm64平台的可执行程序kernellogd。android studio开发流程此处不讨论,直接贴几句核心代码如下:

具体步骤如下:

内置kernellogd可执行二进制文件到系统

如何内置可以参考之前的文章:

玩转Android10源码开发定制(九)内置frida-gadget so文件和frida-server可执行文件到系统

配置kernellogd到init.rc

安卓10系统源码中,init.rc文件路径为:

system/core/rootdir/init.rc

在init.rc文件末尾添加kernellogd后台服务的配置,内容如下:

修改init.te文件,配置init进程可以执行kernellogd命令的seandroid权限

涉及修改的init.te文件路径分别如下:

system/sepolicy/public/init.te

system/sepolicy/prebuilts/api/29.0/public/init.te

以上两个文件内容是一样的,需要保证同时被修改。修改如下:

allow init system_file:file {execute_no_trans}语句含义:允许所有属于init域的进程对所有属于system_file类型的文件具有执行权限。

以上配置完成之后编译刷机。
在终端执行adb logcat之后可以看到内核日志和用户空间日志都输出来了。测试数据样本如下:

adb logcat
adb logcat
adb shell logcat
adb shell logcat
adb shell cat /proc/kmsg
adb shell cat /proc/kmsg
adb shell cat /dev/kmsg
adb shell cat /dev/kmsg
adb shell dmesg
adb shell dmesg
void dmesg_main(void)
{
   //...省略
  if (!(toys.optflags&FLAG_S)) {
        //...省略
    fd = open("/dev/kmsg", O_RDONLY|(O_NONBLOCK*!(toys.optflags&FLAG_w)));
    if (fd == -1) goto klogctl_mode;
    lseek(fd, 0, SEEK_DATA);
    for (;;) {
      if (-1==(len = read(fd, msg, sizeof(msg))) && errno==EPIPE) continue;
      // read() from kmsg always fails on a pre-3.5 kernel.
      if (len==-1 && errno==EINVAL) goto klogctl_mode;
      if (len<1) break;
      msg[len] = 0;
      format_message(msg, 1);
    }
    close(fd);
  } else {
    char *data, *to, *from, *end;
    int size;
 
klogctl_mode:
    // Figure out how much data we need, and fetch it.
    if (!(size = TT.size)) size = xklogctl(10, 0, 0);
    data = from = xmalloc(size+1);
    data[size = xklogctl(3+(toys.optflags&FLAG_c), data, size)] = 0;
 
    // Send each line to format_message.
    to = data + size;
    while (from < to) {
      if (!(end = memchr(from, '\n', to-from))) break;
      *end = 0;
      format_message(from, 0);
      from = end + 1;
    }
 
    if (CFG_TOYBOX_FREE) free(data);
  }
no_output:
  // Set the log level?
  if (toys.optflags & FLAG_n) xklogctl(8, 0, TT.level);
  // Clear the buffer?
  if (toys.optflags & (FLAG_C|FLAG_c)) xklogctl(5, 0, 0);
}
void dmesg_main(void)
{
   //...省略
  if (!(toys.optflags&FLAG_S)) {
        //...省略
    fd = open("/dev/kmsg", O_RDONLY|(O_NONBLOCK*!(toys.optflags&FLAG_w)));
    if (fd == -1) goto klogctl_mode;
    lseek(fd, 0, SEEK_DATA);
    for (;;) {
      if (-1==(len = read(fd, msg, sizeof(msg))) && errno==EPIPE) continue;
      // read() from kmsg always fails on a pre-3.5 kernel.
      if (len==-1 && errno==EINVAL) goto klogctl_mode;
      if (len<1) break;
      msg[len] = 0;
      format_message(msg, 1);
    }
    close(fd);
  } else {
    char *data, *to, *from, *end;
    int size;
 
klogctl_mode:
    // Figure out how much data we need, and fetch it.
    if (!(size = TT.size)) size = xklogctl(10, 0, 0);
    data = from = xmalloc(size+1);
    data[size = xklogctl(3+(toys.optflags&FLAG_c), data, size)] = 0;
 
    // Send each line to format_message.
    to = data + size;
    while (from < to) {
      if (!(end = memchr(from, '\n', to-from))) break;
      *end = 0;
      format_message(from, 0);
      from = end + 1;
    }
 
    if (CFG_TOYBOX_FREE) free(data);
  }
no_output:

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2021-4-12 22:08 被蟑螂一号编辑 ,原因:
收藏
免费 3
支持
分享
最新回复 (4)
雪    币: 355
活跃值: (435)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2

谢谢分享 
2021-1-8 07:44
0
雪    币: 729
活跃值: (1321)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
3
谢谢分享 
2021-8-19 12:30
0
雪    币: 5924
活跃值: (3989)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
这个是不是必须得手机启动进入桌面后才可以看,而且只能看到系统启动完成后的日志?
2022-7-17 00:04
0
雪    币: 1
活跃值: (150)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
老板接开发吗?可否留个联系方式
2023-4-1 22:34
0
游客
登录 | 注册 方可回帖
返回
//