• tracepoint: 定义函数及调用示例


    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. 源码下载


    内容


    1. tracepoint示例

      首先创建一个文件夹,用于保存相关文件,示例文件夹名称为pci。

    在这里插入图片描述


    1.1 编写test_trace.h文件

      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 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    1.2 编写test.c文件

      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");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    1.3 编写Makefile文件

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2. 操作说明

    ## 说明
    
    	本示例用于内核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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3. tracepoint部分定义分析

    • subsys_eventname 定义事件唯一的标识符
    • subsys 子系统的名称
    • eventname 跟踪的事件的名称
    • TP_PROTO(int firstarg, struct task_struct *p) 此跟踪点调用的函数的原型
    • TP_ARGS(firstarg, p) 参数名称,与原型中的相同
    • 如果您在多个源文件中使用,#define CREATE_TRACE_POINTS 应该只出现在一个源文件中
    • TP_STRUCT__entry 输出结构定义:
      1. __array 数组参数
      2. __field 类型参数
    • TP_fast_assign 输出结构的参数赋值
    • TP_printk 打印信息

    4. 源码下载

    资源下载地址

  • 相关阅读:
    python深度学习入门-从零构建CNN和RNN
    Notepad++ 通过HexEditor插件查看.hprof文件、heap dump文件的堆转储数据
    2022-08-29 第六小组 瞒春 学习笔记
    Qt - Qt5事件处理(鼠标事件)
    [计算机系统]:理解指针
    全网最完整php 禁止eval函数讲解
    开启金融之门,一切皆有可能——人大女王金融硕士项目助您成就辉煌
    pat 1145
    数据分析-相关性
    Matlab图像处理-模式识别
  • 原文地址:https://blog.csdn.net/a29562268/article/details/126208684