概念

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

列出文件夹下文件:

root@:/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个文件文件夹:

root@:/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文件夹下结构例如以下:

root@:/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中。看下结果:

root@:/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
# | | | |||| | |
root@:/sys/kernel/debug/tracing # echo 1 > events/readahead/do_file_map/enable
root@:/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应用中介绍~

Linux trace使用入门的更多相关文章

  1. Linux运维入门到高级全套常用要点

    Linux运维入门到高级全套常用要点 目 录 1. Linux 入门篇................................................................. ...

  2. Linux Shell脚本入门--cut命令

    Linux Shell脚本入门--cut命令 cut cut 命令可以从一个文本文件或者文本流中提取文本列. cut语法 [root@www ~]# cut -d'分隔字符' -f fields &l ...

  3. Linux基础知识入门

    [Linux基础]Linux基础知识入门及常见命令.   前言:最近刚安装了Linux系统, 所以学了一些最基本的操作, 在这里把自己总结的笔记记录在这里. 1,V8:192.168.40.10V1: ...

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

    http://www.oschina.net/code/snippet_222919_11734 代码分享 当前位置: 代码分享 » Java  » 网络编程 搜 索   [饶过] 使用Java管理千 ...

  5. linux grep 从入门到精通

    linux grep 从入门到精通 一.初级 搜索日志 grep "186" catalina.out 在新输出日志中监听固定字符串 tail -f catalina.out | ...

  6. linux系统基础入门

    使用工具:源码管理,自动部署,web服务器(linux) linux系统基础入门 1.下载地址 2.本文介绍的是一个基于Ubuntu的开源操作系统 下载优麒麟 Ubuntu是一个广泛应用于个人电脑,云 ...

  7. Linux Shell脚本入门--wget 命令用法详解

    Linux Shell脚本入门--wget 命令用法详解 wget是在Linux下开发的开放源代码的软件,作者是Hrvoje Niksic,后来被移植到包括Windows在内的各个平台上.它有以下功能 ...

  8. Linux Shall命令入门

    Linux Shall命令入门 ifconfig                                            //查看ip信息 service network start   ...

  9. Linux系统快速入门方法

    相信看到这篇文章的你一定是想要学习Linux,或者已经在学习Linux的人了,那我们就可以一起探讨一下,学习Linux如何快速入门呢? 首先,希望大家弄清楚自己为什么要学习Linux,有的人是因为兴趣 ...

随机推荐

  1. 提高Java开发效率,Idea必装的几款插件

    1.codeMaker 重复代码生成工具 domian和dto两个类基本差不多,这个工具就可以通过一个类快速生成另一个类. 2.gsonFormat json转换成Java类 很多时候根据别人接口给的 ...

  2. bugs view:

    Expecially those business bugs! I should check better especially when data changes! This place requi ...

  3. 时间戳/Date(1354116249000)/ 转换

    从C#的Datatime格式通过Json传到Js里面,时间会显示成时间戳/Date(1354116249000)/ ,js转化如下 function GetDateFormat(str) { retu ...

  4. [LeetCode] Longest Common Prefix 字符串公有前序

    Write a function to find the longest common prefix string amongst an array of strings. Hide Tags Str ...

  5. hdu 5952 Counting Cliques 求图中指定大小的团的个数 暴搜

    题目链接 题意 给定一个\(n个点,m条边\)的无向图,找出其中大小为\(s\)的完全图个数\((n\leq 100,m\leq 1000,s\leq 10)\). 思路 暴搜. 搜索的时候判断要加进 ...

  6. RSTP介绍

    1. 介绍 RSTP(Rapid Spanning Tree Protocol),快速生成树协议,标准为802.1w(已合入802.1D-2004)RSTP是对STP技术的修改和补充,最大特点就是快速 ...

  7. vim 搜尋取代功能

    VI 的搜尋取代語法格式大致如下 :[範圍]s/[比對字串]/[取代字串]/[g,c,i] 範圍部分: 範圍表示法為開頭 , 結束 假如我要從第 1 行到第 150 行,可以這樣下: 1, 150 假 ...

  8. smtp发送邮件记得结尾发送"\r\n.\r\n"

    前段时间老板安排我修复一个邮件服务器后台C程序的bug,这个功能是邮件强制发送功能,从邮件管理后台将垃圾邮件发送出去. 因为服务器是debian系统,所以我用dbg配合日志大致跟踪后,追踪到了读取邮件 ...

  9. python 生成式和生成器

    #!/usr/bin/env python # -*- coding:utf-8 -*- # @Time : 2017/10/17 21:46 # @Author : lijunjiang # @Fi ...

  10. Day 22 Object_oriented_programming 3

    isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象,如果是返回True 1 class F ...