Linux trace使用入门

给嵌入式开发者的Lauterbach TRACE32入门指南:从软件下载到硬件连接(Windows/Linux双平台) 本文为嵌入式开发者提供Lauterbach TRACE32的入门指南,涵盖从软件下载到硬件连接的全过程,包括Windows和Linux双平台的安装步骤、常见问题解决方案及效率提升技巧。帮助开发者快速掌握TRACE32调试工具的使用,提升嵌入式开发效率。 阅读详情
AI摘要

本文深入探讨Linux内核中的Trace机制,包括其概念、挂载及使用方法,并通过实例展示了如何添加自定义Trace事件来追踪系统行为。

概念

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

撰写不易,转载需注明出处:http://blog.youkuaiyun.com/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学习(一)——trace配置及描述 备注:1. Kernel版本:4.19.1232. 使用工具:Source Insight 4.0。 阅读详情

相关推荐

Linux调试中的各种trace

Linux调试中的各种trace | DD'NotesLinux调试中的各种traceLinux中有很多调试手段,很多trace,很让人迷糊,弄得云里雾里。今天简单介绍下其中的几种trace:ptrace, strace, ltrace, ftrace。只是简单介绍它们的基本概念,对其有基本的了解,后面有机会的话,再逐个深入。ptrace官方手册说明:https://man7.org/linux/man-pages/man2/ptrace.2.hLinux调试中的各种trace | DD'Notes。

DD'Notes 2090

linux trace学习(二)——trace使用

备注:1. Kernel版本:4.19.1232. 使用工具:Source Insight 4.0。

枫潇潇 9612

非常有用的Linux网络诊断命令:traceroute

traceroute 是一个网络诊断工具,用于检测数据包从本机到目标主机经过的路由路径。它可以帮助我们分析出网络连接的瓶颈,定位网络问题,并帮助我们优化网络连接。在 Linux 系统中,traceroute 命令是一个非常常用的工具。traceroute 是一个非常有用的网络诊断工具,可以帮助我们分析出网络连接的瓶颈,定位网络问题,并帮助我们优化网络连接。本文介绍了 traceroute 的基本语法和常用参数,以及其工作原理和输出解释,希望能够帮助读者更好地了解和掌握 traceroute 的使用。

网络技术联盟站 2590

linux中trace命令,linux traceroute 命令详解

功能说明:显示数据包到主机间的路径。语  法:traceroute[-dFlnrvx][-f][-g...][-i][-m][-p][-s][-t][-w][主机名称或IP地址][数据包大小]补充说明:traceroute指令让你追踪网络数据包的路由途径,预设数据包大小是40Bytes,用户可另行设置。参  数:-d 使用Socket层级的排错功能。-f 设置第一个检测数据包的存活数值TTL的大小...

weixin_35698867的博客 1万+

TRACE32快速入门:安装、硬件连接与首次halt避坑

嵌入式调试环境搭建通常从调试器驱动安装、USB枚举识别和JTAG/SWD物理链路连接切入。其原理是宿主工具通过主模块与目标芯片调试口建立握手,架构支持库、上下电顺序和配置文件共同决定首次连接是否成功。稳定的调试环境能减少“连不上、CPU列表空白、配置互相覆盖”等重复排查,对固件开发、多机环境复现和自动化调试流程都有直接价值。围绕TRACE32快速入门,安装包选择、LA-3505等主模块连接、config.t32隔离和cmm脚本固化,构成了从零到首次halt的关键工程实践。

weixin_29163857的博客 54

TRACE32嵌入式调试器入门:安装配置与JTAG连接实战

在嵌入式开发中,printf调试只能覆盖预设的打印点,遇到程序跑飞、指针越界或时序被扰动时,往往束手无策。硬件调试器通过JTAG等专用调试接口直接读取CPU内部状态,实现暂停、观察寄存器、修改内存、回溯执行轨迹,真正打开芯片这个“黑匣子”。掌握调试器已成为单片机与车规芯片开发的必备技能,而TRACE32凭借广泛架构覆盖与强大脚本生态,成为业界常用工具。入门第一步是从安装环境开始:正确选择安装包类型、勾选匹配的芯片平台、理清硬件接线与上下电顺序,并避开驱动识别失败等常见坑。完成环境搭建后,即可连接目标板,体验

weixin_29159127的博客 162

Linux最全Linux命令:traceroute命令(路由跟踪),分享面经

最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!

2401_84139697的博客 4562

TRACE32调试器入门:从安装配置到硬件连接与启动流程详解

嵌入式调试工具是开发流程中不可或缺的一环,其原理在于通过调试接口与目标芯片建立通信链路,实现对程序运行状态的控制与观测。成熟的调试平台能显著提升问题定位效率,在汽车电子、工业控制等领域应用广泛。以劳特巴赫TRACE32为例,它支持ARM、Tricore、PowerPC等多种主流架构,覆盖从芯片验证到量产维护的完整生命周期。对于初次接触的开发者而言,掌握调试器的环境搭建与基本操作是高效工作的前提。本文围绕TRACE32的软件安装、平台选择、硬件连接顺序、上下电时序以及常见启动问题的处理展开,帮助读者建立一套从

weixin_26833139的博客 229

Linux/Android 跟踪技术:ftrace、TRACE_EVENT、atrace、systrace 与 perfetto 入门

如果 ftrace 原始 trace 里有,Perfetto 里没有,通常是 Perfetto 配置没有包含对应。事件源 → tracefs 开关 → per-CPU ring buffer → trace/trace_pipe/perfetto → 时间线分析解决“我现在想快速知道这里发生了什么”,解决“这个事件以后还要被稳定观测”,解决“如何在 Android 上采集和查看”。把这三层关系理清后,面对卡顿、IRQ 延迟、线程调度、驱动响应慢等问题,就能从日志排查升级到时间线排查。

永远年轻 永远热泪盈眶 931

劳特巴赫TRACE32入门:从安装接线到芯片识别与调试避坑

嵌入式调试的核心,是通过JTAG等调试接口让调试器与目标芯片内核建立可控连接,从而暂停程序、查看内存与寄存器,并借助Trace跟踪还原指令执行过程。相比串口打印的“猜谜式”排查,这种可视化调试能更快定位跑飞、指针越界和外设配置错误,广泛应用于汽车电子、电机控制及MCU底层开发。劳特巴赫TRACE32正是这一链路的典型工具组合,入门时先完成软件安装、硬件接线、正确上下电,并在PowerView中确认目标芯片识别,再逐步练习断点、单步和cmm脚本,环境稳定比功能贪多更重要。

weixin_29191081的博客 47

PTPX功耗分析实战——从脚本配置到报告解读

本文详细介绍了PTPX功耗分析的全流程,从脚本配置到报告解读,帮助工程师快速掌握芯片设计中的功耗估算技术。文章涵盖了环境搭建、波形文件处理、功耗报告解析等关键环节,并提供了实战经验和优化建议,特别适合需要提升PTPX功耗分析效率的开发者。

weixin_29248313的博客 279

trace32入门使用

项目中接触到需要用劳特巴赫调试代码的部分,之前从没接触过。今天简单来学习总结一下具体的使用方法。截图都是来源自trace32官方的培训视频。

随手分享工作中的知识,沉淀积累 6673

S32K314 EB配置MCAL全模块讲解【Autosar——1 MCU模块详解】持续更新中

FIRC(fast internal RC Oscillator) :高速内部时钟,固定48MHZ;SIRC(Slow Internal RC Oscillator):低速内部时钟,固定32KHZ;FXOSC(Fast Crystal Oscillator Digital Controller):高速外部晶振(8-40MHZ),根据原理图选型进行配置;SXOSC():外部低速外部时钟,固定输入32.768KHZ;PLL_PHIn_CLK:时钟倍频锁相环时钟范围(640-1280MHZ);

qq_40488886的博客 1782

T2080 U-BOOT与OS内核移植 准备篇(二)——开发调试环境入门(Trace32、QorIQ Linux SDK和QCVS)

T2080 U-BOOT与OS内核移植 准备篇(二)——开发调试环境入门一、Trace32二级目录三级目录 上一篇我们简单介绍了几种常用与T2080的开发调试工具和环境。这篇文章将带领大家进行环境的部署和配置。 回顾一下我们选择的工具集: 1.Trace32 用途一:基础资源(片上寄存器/片上SRAM、内存、FLASH和串口等)的可用性验证。 用途二:PBL(RCW)、u-boot和OS(对于Linux包括kernel、dtb和rtfs的烧录)。 用途三:RCW、u-boot和OS kernel代码调试(单

weixin_49274884的博客 2508

scanpy单细胞转录组python教程(四):单样本数据分析之降维聚类及细胞注释

本文介绍了使用scanpy进行单细胞转录组分析的降维聚类和细胞注释流程。首先通过PCA降维并可视化主成分贡献,然后使用不同分辨率参数(0.2-1.0)进行Leiden聚类。通过Wilcoxon检验鉴定marker基因,并基于经典marker基因手动注释细胞类型。最后对低质量细胞群进行过滤,并重新计算邻居图和UMAP可视化。流程中包含PCA方差分析、多分辨率聚类比较、marker基因筛选和基于UMAP的细胞类型可视化等关键步骤,为后续分析奠定基础。

qq_42090739的博客 942

TEC控制器芯片 ADN8835 中文数据手册

ADN8835是一款高集成度的单芯片TEC控制器。它包括线性电压调节模块脉冲宽度调制(PWM) 电压调节模块和两个零漂移、轨到轨斩波放大器。线性控制器和PWM驱动器用于控制H桥配置中的内部功率MOSFET。通过测量热传感器反馈电压,并使用集成的运算放大器作为比例-积分-微分(PID)补偿器来调理信号,ADN8835通过TEC驱动电流,将连接至TEC模块的激光二极管或无源组件的温度稳定到编程的目标温度。

lu2289504634的博客 9538

Perfetto 入门指南:按开发者角色快速定位你的第一条 Trace 与 Profiling 方案

Perfetto 是一套面向客户端(client-side)系统的开源 tracing、profiling 与分析工具套件,其官方文档体系庞大,包含概念、教程(Tutorials)、Cookbook、Case Study 等大量页面,新手往往不知道从哪一页读起。本文以仓库中的 [docs/getting-started/start-using-perfetto.md](https://link.g

gitblog_01194的博客 76

Unity URP 深度解析:利用Stencil与RenderFeature实现高效遮挡高亮

本文深入解析Unity URP中利用Stencil与RenderFeature实现高效遮挡高亮的技术方案。通过模板缓冲机制和自定义RenderFeature,开发者可以在保持场景完整性的同时,清晰标识被遮挡物体位置,提升游戏体验。文章详细介绍了Shader编写、URP管线配置及性能优化技巧,并提供了常见问题排查方法。

weixin_29012677的博客 479

Linux 调试之 TRACE_EVENT(三)

Linux 调试之 TRACE_EVENT知识简介

小立仔 3397

机器学习-深嵌交叉验证(Nested Cross-Validation)

Section I: Code and Analyses 第一部分:代码 from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.svm import SVC from...

Santorinisu Blogs 2716

DMR对讲机的基本概念理解

刚刚入手DMR对讲机,尚未成功联通。国内互联网上能找到的资料很少,大多数也都是一些DMR协议介绍之类的玩意,对实际操作没有指导意义。以下全部是这几天在网上研究各种资料得出的个人思考,如有错误请斧正。 相比与模拟通讯系统,DMR将语音信号转换为包的形式进行收发。将DMR对比成TCP/IP系统会更容易理解。 一般DMR对讲机都支持模数双通,说明DMR应该使用了跟FM同样的无线AP组件,只在解码上有区别。对讲机先使用DMR进行数字解码,解码成功则说明是数字信号,不成功则使用模拟方式再次进行解码。可以对等理解为

1万+
上一篇: Android——bootchart
下一篇: ARM 关键几个寄存器
南丶烟
博客等级 码龄14年 569粉丝 98原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值