Linux trace使用入门

概念

trace 顾名思义追踪信息,可通俗理解为一种高级打印机制,用于debug,实现追踪kernel中函数事件的框架。源代码位于:\kernel\trace\trace.c,有兴趣能够研究

撰写不易,转载需注明出处:http://blog.csdn.net/jscese/article/details/46415531本文来自 【jscese】的博客。

终端使用

须要文件系统挂载完毕之后,kernel的debugfs 挂载到 /sys/kernel/debug ,也可用命令挂载,一般都是在.rc中:

mount debugfs none /sys/kernel/debug

列出文件夹下文件:

[email protected]:/sys/kernel/debug/tracing # ll
-r--r--r-- root     root            0 1970-01-01 08:00 README
-r--r--r-- root     root            0 1970-01-01 08:00 available_events
-r--r--r-- root     root            0 1970-01-01 08:00 available_tracers
-rw-rw-r-- root     shell           0 1970-01-01 08:00 buffer_size_kb
-r--r--r-- root     root            0 1970-01-01 08:00 buffer_total_size_kb
-rw-r--r-- root     root            0 1970-01-01 08:00 current_tracer
drwxr-xr-x root     root              1970-01-01 08:00 events
-rw-r--r-- root     root            0 1970-01-01 08:00 free_buffer
drwxr-xr-x root     root              1970-01-01 08:00 instances
drwxr-xr-x root     root              1970-01-01 08:00 options
drwxr-xr-x root     root              1970-01-01 08:00 per_cpu
-r--r--r-- root     root            0 1970-01-01 08:00 printk_formats
-r--r--r-- root     root            0 1970-01-01 08:00 saved_cmdlines
-r--r--r-- root     root            0 1970-01-01 08:00 saved_tgids
-rw-r--r-- root     root            0 1970-01-01 08:00 set_event
-rw-rw---- root     shell           0 1970-01-01 08:00 trace
-rw-rw-r-- root     shell           0 1970-01-01 08:00 trace_clock
--w--w--w- root     root            0 1970-01-01 08:00 trace_marker
-rw-r--r-- root     root            0 1970-01-01 08:00 trace_options
-r--r--r-- root     root            0 1970-01-01 08:00 trace_pipe
-rw-r--r-- root     root            0 1970-01-01 08:00 tracing_cpumask
-rw-rw-r-- root     shell           0 1970-01-01 08:00 tracing_on
-rw-r--r-- root     root            0 1970-01-01 08:00 tracing_thresh

版本号不同,可能会有出入,我这边(3.10.37)。列出几个经常使用的:

README能够去看看,介绍了一些属性。

available_* : 代表支持有效的 事件 和追踪器 ,都能够使用cat 查看。

buffer_size_kb:这个属性比較重要,也是使用中须要注意的,这是设置启动的CPU的缓存大小。取决于追踪log的大小,超出会反复利用覆盖,可是一次性分配又须要考虑内存。

buffer_total_size_kb:这个就是总和buffer size 了,启用了多少个cpu去trace就乘以buffer_size_kb.

current_tracer: 当前的追踪器。有哪几种能够查看available_tracers ,用echo * > 重定向 设置改变,详细tracer的不同需另行參考 ,默觉得nop

events:文件夹下就是加入在kernel源代码中已经存在的各个event集合。

free_buffer:顾名思义,可是这个使用方法比較特殊,有仅仅要open之后。等处理完buffer之后 close这个文件就可以释放buffer,有兴趣能够去trace.c里面看看这个节点的file_operation,不手动去close这个节点的话,上面设置的buffer是不会free的。

trace:用于追踪操作的文件节点,就是读取该节点获取trace log

tracing_cpumask:用到的cpu标记。以数值bit位表示多少个cpu,这个尤为注意。比方四核 cat显示就是 “f” 也就是“1111”。

tracing_on:开关



我这里仅仅是简单的列出我用到过的几项。须要尤为注意的就是buffer free cpubit 假设没弄好就大量内存泄露了~前车之鉴

对于节点定义以及使用方法,不妨耐心阅读kernel自带的doc:\kernel\Documentation\trace 文件夹下有非常多文档可看


加入trace event

上面说了是为了追踪执行信息,以我为readahead加入的trace event为例,抓取readahead所需的event log用于分析.

kernel中event定义的源代码路径:\kernel\include\trace\events

路径下加入一个我为了这个功能新增的头文件readahead.h 内容例如以下:

#undef TRACE_SYSTEM
#define TRACE_SYSTEM readahead

#if !defined(_TRACE_READAHEAD_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_READAHEAD_H

#include <linux/tracepoint.h>

TRACE_EVENT(do_open_exec,

    TP_PROTO(struct inode *inode),

    TP_ARGS(inode),

    TP_STRUCT__entry(
            __field(    dev_t,  dev         )
            __field(    ino_t,  ino         )
    ),

    TP_fast_assign(
            __entry->dev    = inode->i_sb->s_dev;
            __entry->ino    = inode->i_ino;
    ),

    TP_printk("%d %d %lu",
          MAJOR(__entry->dev), MINOR(__entry->dev),
          (unsigned long) __entry->ino)
);

TRACE_EVENT(do_fs_read,

    TP_PROTO(struct inode *inode,unsigned long pos,size_t count),

    TP_ARGS(inode,pos,count),

    TP_STRUCT__entry(
            __field(    dev_t,  dev         )
            __field(    ino_t,  ino         )
            __field(    unsigned long,  pos         )
            __field(    size_t, count           )
    ),

    TP_fast_assign(
            __entry->dev    = inode->i_sb->s_dev;
            __entry->ino    = inode->i_ino;
            __entry->pos    =pos;
            __entry->count  =count;
    ),

    TP_printk("%d %d %lu %lu %d",
          MAJOR(__entry->dev), MINOR(__entry->dev),
         __entry->ino,__entry->pos,__entry->count)
);

TRACE_EVENT(do_file_map,

    TP_PROTO(struct inode *inode,unsigned long pageshift, unsigned long pagesize),

    TP_ARGS(inode,pageshift,pagesize),

    TP_STRUCT__entry(
            __field(    dev_t,  dev         )
            __field(    ino_t,  ino         )
            __field(    unsigned long , pageshift           )
            __field(    unsigned long,  pagesize            )
    ),

    TP_fast_assign(
            __entry->dev    = inode->i_sb->s_dev;
            __entry->ino    = inode->i_ino;
            __entry->pageshift  =pageshift;
            __entry->pagesize   =pagesize;
    ),

    TP_printk("%d %d %lu %lu %d",
          MAJOR(__entry->dev), MINOR(__entry->dev),
          (unsigned long) __entry->ino,__entry->pageshift,__entry->pagesize)
);

#endif
#include <trace/define_trace.h>

编译进系统,可到终端去查看event文件夹下是否生成了定义的这3个文件文件夹:

[email protected]:/sys/kernel/debug/tracing/events # ll readahead/
drwxr-xr-x root     root              1970-01-01 08:00 do_file_map
drwxr-xr-x root     root              1970-01-01 08:00 do_fs_read
drwxr-xr-x root     root              1970-01-01 08:00 do_open_exec
-rw-r--r-- root     root            0 1970-01-01 08:00 enable
-rw-r--r-- root     root            0 1970-01-01 08:00 filter

每一个相应的event文件夹下结构例如以下:

[email protected]:/sys/kernel/debug/tracing/events/readahead # ll do_file_map/
-rw-r--r-- root     root            0 1970-01-01 08:00 enable
-rw-r--r-- root     root            0 1970-01-01 08:00 filter
-r--r--r-- root     root            0 1970-01-01 08:00 format
-r--r--r-- root     root            0 1970-01-01 08:00 id

这里文件节点所代表的意义,以及假设初始配置 在上面说到的kernel相应doc的trace/events.txt中有详细的解析,不多阐述。



能够看到上面3个event,每一个传入的參数是不一样的,定义之后就是使用了,加入3处trace event位置例如以下:

直接贴kernel 文件夹下的git patch:

diff --git a/fs/exec.c b/fs/exec.c
index a0d09ca..0954060 100755
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -66,6 +66,8 @@

 #include <trace/events/sched.h>

+#include <trace/events/readahead.h>

 int suid_dumpable = 0;

 static LIST_HEAD(formats);
@@ -748,6 +750,17 @@ EXPORT_SYMBOL(setup_arg_pages);

 #endif /* CONFIG_MMU */

 struct file *open_exec(const char *name)
 {
    struct file *file;
@@ -793,6 +806,21 @@ struct file *open_exec(const char *name)
    }
 #endif

+/*===================*/
+   /*(add trace for readahead)*/
+   struct inode *inode = file->f_path.dentry->d_inode;
+   if (inode && inode->i_ino && MAJOR(inode->i_sb->s_dev)) {
+
+       trace_do_open_exec(inode);
+   }
+
+
+/*end*/
+
+
 out:
    return file;

diff --git a/fs/read_write.c b/fs/read_write.c
index c6a3a68..156ebff 100755
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -22,6 +22,8 @@
 #include <asm/uaccess.h>
 #include <asm/unistd.h>

+#include <trace/events/readahead.h>
+
 typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
 typedef ssize_t (*iov_fn_t)(struct kiocb *, const struct iovec *,
        unsigned long, loff_t);
@@ -376,6 +378,26 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
    }
 #endif

+
+   /*(add trace for readahead)*/
+
+   if (S_ISREG(file->f_dentry->d_inode->i_mode)
+           && MAJOR(file->f_dentry->d_inode->i_sb->s_dev)) {
+
+       unsigned long ulpos=(unsigned long) *pos;
+
+       trace_do_fs_read(file->f_dentry->d_inode,ulpos,count);
+
+   }

+
+   /*end*/
+

+
    ret = rw_verify_area(READ, file, pos, count);
    if (ret >= 0) {
        count = ret;

diff --git a/mm/filemap.c b/mm/filemap.c
index 84a6422..e04ed31 100755
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -38,6 +38,8 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/filemap.h>

+
+#include <trace/events/readahead.h>
 /*
  * FIXME: remove all knowledge of the buffer layer from the core VM
  */
@@ -1623,6 +1625,13 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        offset << PAGE_SHIFT, PAGE_SIZE);
 #endif

+   /*(add trace for readahead)*/
+
+   trace_do_file_map(inode,offset << PAGE_SHIFT,PAGE_SIZE);
+
+   /*end*/
+
+
    size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
    if (offset >= size)
        return VM_FAULT_SIGBUS;


当须要trace log的时候,就须要使能event,也就是打开上面每一个event相应文件夹下的节点enable,(trace版本号不同开关会不同,要视详细情况而定了)trace机制就会运作抓取事件到buffer中。看下结果:

[email protected]:/sys/kernel/debug/tracing # cat trace
# tracer: nop
#
# entries-in-buffer/entries-written: 0/0   #P:1
#
#                              _-----=> irqs-off
#                             / _----=> need-resched
#                            | / _---=> hardirq/softirq
#                            || / _--=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
[email protected]:/sys/kernel/debug/tracing # echo 1 > events/readahead/do_file_map/enable
[email protected]:/sys/kernel/debug/tracing # cat trace
# tracer: nop
#
# entries-in-buffer/entries-written: 1100/1100   #P:1
#
#                              _-----=> irqs-off
#                             / _----=> need-resched
#                            | / _---=> hardirq/softirq
#                            || / _--=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
     InputReader-517   [000] ...1  6270.548499: do_file_map: 93 32 58 41598976 4096
     InputReader-517   [000] ...1  6270.548540: do_file_map: 93 32 58 41594880 4096
     InputReader-517   [000] ...1  6270.548641: do_file_map: 93 32 58 48373760 4096
     InputReader-517   [000] ...1  6270.577857: do_file_map: 93 16 1290 188416 4096
     InputReader-517   [000] ...1  6270.578380: do_file_map: 93 16 1290 184320 4096
...

这打印出来的数据格式前面的都有凝视,后面的一串数据,就是之前readahead.h中定义的TP_printk

仅仅做简单的介绍,实际代码应用在兴许readahead应用中介绍~

时间: 2024-10-19 19:49:45

Linux trace使用入门的相关文章

使用Java管理千台规模Linux服务器_入门

http://www.oschina.net/code/snippet_222919_11734 代码分享 当前位置: 代码分享 » Java  » 网络编程 搜 索 [饶过] 使用Java管理千台规模Linux服务器_入门 rgone 发布于 2012年07月09日 10时, 24评/2769阅 分享到:  收藏 +43 踩顶0 前东家是一家游戏公司,老板很好,当时工作也留下了很多自己原创的管理脚本.现在分享一下在办公环境使用Java.Jsch登录VPN管理Linux的脚本(此处实现JAVA调

Linux Shell脚本入门--cut命令

Linux Shell脚本入门--cut命令 cut cut 命令可以从一个文本文件或者文本流中提取文本列. cut语法 [[email protected] ~]# cut -d'分隔字符' -f fields <==用于有特定分隔字符 [[email protected] ~]# cut -c 字符区间 <==用于排列整齐的信息 选项与参数: -d :后面接分隔字符.与 -f 一起使用: -f :依据 -d 的分隔字符将一段信息分割成为数段,用 -f 取出第几段的意思: -c :以字符 (

Linux运维入门到高级全套系列PDF

Linux运维入门到高级全套系列PDF(转) [日期:2016-08-01] 来源:Linux社区  作者:Linux [字体:大 中 小] Linux 学习技巧 初学者可以自己安装虚拟机,然后把 Linux 常用命令例如 cd.ls.chmod.useradd.vi 等等多练习几十遍,把自己敲打命令的熟练程度提升上来. 然后根据文档搭建 Linux 下常见的各种服务  (DHCP. SAMBA. DNS.Apache.Mysql 等) ,遇到问题后可以在 google 搜索,搜索的时候多看几篇

马哥LINUX高薪LINUX高薪就业入门教程-虚拟机篇幅-学习笔记-11

课程名称:马哥Linux高薪就业入门-安装学习VMware Workstation9-1 课程主要内容:虚拟机安装及OS系统配置说明 虚拟机硬件配置: CPU,Memory,I/O(disk,Ethercard) 虚拟机关键字: 1.disk image file(磁盘映像文件) 2.Sparse(稀疏格式) 3.CPU超线程 虚拟机使用技巧: 1.虚拟机磁盘建议放置空间大,分区编号越小性能越好,对于不常用的文件就放到最外层的: 2.CPU一级缓存最高,二级缓存价格次之,一级缓存容量翻倍基本价格

Linux基础知识入门

[Linux基础]Linux基础知识入门及常见命令. 前言:最近刚安装了Linux系统, 所以学了一些最基本的操作, 在这里把自己总结的笔记记录在这里. 1,V8:192.168.40.10V1:192.168.40.11Linux ip:192.168.40.128 2,Linux是一个操作系统, 与windows的区别:Linux:图形化界面简单,性能很快,在企业中当做服务器来使用.Windows:图形化界面很炫,性能相对差,大众用户.windows的服务器: windows2003,win

Linux常用命令-入门篇(一)

1    For循环 语法:begin for i in reverse 1..10 loop insert into users values(i,'奥巴马'): end loop: end; 注意:循环变量 i 是隐含增加的,所以无法看到 2    goto语句 goto 语句用于跳转到特定的位置去执行语句.由于goto语句会减少程序的可读性,所以一般情况下 不建议使用goto语句 3    null语句 null语句不会执行任何操作,但是可以增加程序的可读性 4    创建返回值是一个结果

Linux设备驱动入门

设备驱动的作用 任何一个计算机系统的运转都是系统中软硬件共同作用的结果,计算机系统的软硬件互相成就了对方. 应用软件工程师需要看到一个没有硬件的纯粹的软件世界,硬件必须被透明地呈现.驱动工程师来实现硬件对软件工程师的隐形. 设备驱动充当了硬件和应用软件之间的纽带.在系统中没有操作系统的情况下,工程师可以根据硬件设备的特点自行定义接口.在有操作系统的情况下,驱动的架构由相应的操作系统定义,驱动工程师必须按照相应的架构设计驱动,驱动才能良好的整合进操作系统的内核. 无操作系统时的设备驱动 功能单一.

&lt;LINUX &gt;bash shell 入门 --linux学习笔记

首先说下我个人对于shell的理解,我觉得shell是一种通过各种控制语句将linux命令进行集合实现批处理的一种脚本语言. shell编程入门其实很简单,语法知识并不多,但是高级shell编程就很难,因为shell是用户和linux之间的桥梁,要编写高质量的shell脚本,就需要用户对linux有很全面的认识. 这里我们只分析shell脚本的语法知识,如想透彻的学习linux还需多努力. shell结构       1.#!指定执行脚本的shell 2.#注释行 3.命令和控制结构 创建she

Linux程序设计从入门到精通(理论讲解+实际演示+项目实战)视频教程

Linux程序设计从入门到精通(理论讲解+实际演示+项目实战)视频教程下载    联系QQ:1026270010 本门课程的最终目的: 这门课程主要突出“实用”的C语言,即我们重点详细讲解真实项目开发和运用中实际运用的C语言知识,及容易犯错的地方,包括对一个C程序怎么去调试的技术.这有别于大学里直接去讲诉C语言的内容,也有别于全国计算机考试二级C里针对考试的C课程.这是一门实用的C语言课程,是你以后从事C语言开发过程中最需要的知识.当然,如果这个课程你认真的听过之后,面对大学的课程或者全国计算机