tracepoint用于内核中的源码调试使用,通过定义新的trace事件来输出需要的参数。下面是Documentation/trace/tracepoints.rst中的描述:
放置在代码中的跟踪点(tracepoint)提供了一个挂钩来调用您可以在运行时提供的函数(探针)。 跟踪点可以是“on”(一个探针连接到它)或“off”(没有连接探针)。 当跟踪点“关闭”时,它没有任何效果,除了添加微小的时间损失(检查分支条件)和空间损失(在检测函数的末尾为函数调用添加几个字节并添加数据 结构在一个单独的部分)。 当跟踪点“打开”时,每次执行跟踪点时都会在调用者的执行上下文中调用您提供的函数。 当提供的函数结束执行时,它返回给调用者(从跟踪点站点继续)。
您可以在代码中的重要位置放置跟踪点。 它们是轻量级的钩子,可以传递任意数量的参数,这些参数的原型在头文件中的跟踪点声明中描述。
它们可用于跟踪和性能计算。
1. tracepoint示例
1.1 编写test_trace.h文件
1.2 编写test.c文件
1.3 编写Makefile文件
2. 操作说明
3. tracepoint部分定义分析
4. 源码下载
首先创建一个文件夹,用于保存相关文件,示例文件夹名称为pci。

test_trace.h文件用于定义跟踪点(桩点)函数信息,TRACE_SYSTEM、defined(TRACE_HEADER_MULTI_READ)和文件末尾的#include
#undef TRACE_SYSTEM
#define TRACE_SYSTEM test_trace
#if !defined(_TEST_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TEST_TRACE_H
#include
TRACE_EVENT(test_trace,
TP_PROTO(struct task_struct *t),
TP_ARGS(t),
TP_STRUCT__entry(
__array( char, comm, TASK_COMM_LEN )
__field( pid_t, pid )
),
TP_fast_assign(
memcpy(__entry->comm, t->comm, TASK_COMM_LEN);
__entry->pid = t->pid;
),
TP_printk("test_trace comm=%s pid=%d", __entry->comm, __entry->pid)
);
#endif
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH /root/pci/
#include
test.c文件属于一个简单的字符驱动示例,通过write函数执行桩点函数trace_test_trace。
#include
#include
#include
#define CREATE_TRACE_POINTS
#include "test_trace.h"
#undef CREATE_TRACE_POINTS
#define CDEVNAME "test"
static int major;
static struct class *dev_class;
static ssize_t test_write(struct file *file, const char __user *buf,
size_t count, loff_t *f_pos)
{
char test[128];
printk("test: cdev_write.\n");
if (copy_from_user(test, buf, count)) {
goto exit;
}
else
*f_pos += count;
trace_test_trace(current);
return count;
exit:
return -1;
}
static const struct file_operations test_fops = {
.owner = THIS_MODULE,
.write = test_write,
};
static int test_init(void)
{
printk("test init.\n");
major = register_chrdev(0, CDEVNAME, &test_fops);
if (major < 0) {
pr_err("test: register_chrdev.\n");
return major;
}
dev_class = class_create(THIS_MODULE, "testclass");
if (IS_ERR(dev_class)) {
unregister_chrdev(major, CDEVNAME);
pr_err("test: class_create.\n");
return PTR_ERR(dev_class);
}
device_create(dev_class, NULL, MKDEV(major, 0), NULL, CDEVNAME);
return 0;
}
static void test_exit(void)
{
printk("test exit.\n");
device_destroy(dev_class, MKDEV(major, 0));
class_destroy(dev_class);
unregister_chrdev(major, CDEVNAME);
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
TAG = test
all:
make -C /lib/modules/`uname -r`/build M=`pwd` modules
rm -rf *.o .*.cmd *.mod.c modules.order Module.symvers .tmp_versions
clean:
rm -rf $(TAG).ko
rm -rf *.o .*.cmd *.mod.c modules.order Module.symvers .tmp_versions
install:
sudo cp $(TAG).ko /lib/modules/`uname -r`/kernel/drivers
obj-m := $(TAG).o
## 说明
本示例用于内核tracepoint演示,分为内核驱动和应用执行操作两部分。
## 编译
首先打开test_trace.h文件,找到TRACE_INCLUDE_PATH宏定义,修改/root/pci/为使用者系统的当前绝对路径,保存文件后执行make。
## 加载驱动
insmod test.ko
## 应用操作
1. 启动test_trace调试点,echo 1 > /sys/kernel/debug/tracing/events/test_trace/enable
2. 输出trace桩点信息,cat /sys/kernel/debug/tracing/trace_pipe
3. 执行write函数(触发trace_*函数),echo testqwerty > /dev/test
TP_PROTO(int firstarg, struct task_struct *p) 此跟踪点调用的函数的原型TP_ARGS(firstarg, p) 参数名称,与原型中的相同#define CREATE_TRACE_POINTS 应该只出现在一个源文件中TP_STRUCT__entry 输出结构定义:
TP_fast_assign 输出结构的参数赋值TP_printk 打印信息