博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux trace使用入门
阅读量:4561 次
发布时间:2019-06-08

本文共 9714 字,大约阅读时间需要 32 分钟。

概念

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

撰写不易,转载需注明出处:本文来自 的博客。

终端使用

须要文件系统挂载完毕之后,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_tracerdrwxr-xr-x root     root              1970-01-01 08:00 events-rw-r--r-- root     root            0 1970-01-01 08:00 free_bufferdrwxr-xr-x root     root              1970-01-01 08:00 instancesdrwxr-xr-x root     root              1970-01-01 08:00 optionsdrwxr-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 
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

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

root@:/sys/kernel/debug/tracing/events # ll readahead/                      drwxr-xr-x root     root              1970-01-01 08:00 do_file_mapdrwxr-xr-x root     root              1970-01-01 08:00 do_fs_readdrwxr-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.cindex a0d09ca..0954060 100755--- a/fs/exec.c+++ b/fs/exec.c@@ -66,6 +66,8 @@ #include 
+#include
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.cindex c6a3a68..156ebff 100755--- a/fs/read_write.c+++ b/fs/read_write.c@@ -22,6 +22,8 @@ #include
#include
+#include
+ 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.cindex 84a6422..e04ed31 100755--- a/mm/filemap.c+++ b/mm/filemap.c@@ -38,6 +38,8 @@ #define CREATE_TRACE_POINTS #include
++#include
/* * 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/enableroot@:/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应用中介绍~

转载于:https://www.cnblogs.com/yangykaifa/p/7238419.html

你可能感兴趣的文章
vue-router组件状态刷新消失的问题
查看>>
Android UI开发第十四篇——可以移动的悬浮框
查看>>
java8的一些用法
查看>>
(十)Hive分析窗口函数(二) NTILE,ROW_NUMBER,RANK,DENSE_RANK
查看>>
2018-11-19站立会议内容
查看>>
第五次作业 关于《构建之法》的心得体会
查看>>
Memo打印1
查看>>
AtCoder Grand Contest 010 --C:Cleaning
查看>>
Memcached 笔记与总结(3)安装 php-memcache(windows 系统下)
查看>>
Android2.2中添加的match_parent和fill_parent没有区别
查看>>
POJ 1251 Jungle Roads (prim)
查看>>
IOS_画图 图片等比压缩 IOS_UIImage
查看>>
刘关张三结义(第七次作业)
查看>>
Redis学习笔记(十一) 命令进阶:Connection(连接)
查看>>
memcached与redis 对比
查看>>
JVM 入门三板斧
查看>>
手机整机方案公司之测试业务流程
查看>>
HeadFIrst Ruby 第二章总结 methods and classes
查看>>
STM32 通用定时器相关寄存器
查看>>
【题解】1621. 未命名
查看>>