“Ftrace”的版本间的差异
来自百问网嵌入式Linux wiki
Zhouyuebiao(讨论 | 贡献) 标签:visualeditor-switched |
|||
第1行: | 第1行: | ||
+ | |||
+ | =Ftrace= | ||
+ | ==文章目的== | ||
+ | : 本文提供了开始使用Linux内核工具所需的基本信息:ftrace [1 ]。 | ||
+ | |||
+ | ==简介== | ||
+ | : 下表简要介绍了该工具及其可用性,具体取决于软件包: | ||
+ | * 是:该工具已经存在(可以使用或激活),也可以在软件包中集成和激活。 | ||
+ | * 没有:该工具不存在且无法集成,或者存在但无法在软件包中激活。 | ||
+ | {| class="wikitable" | ||
+ | !colspan="3" | 工具 | ||
+ | |- | ||
+ | | 名称 | ||
+ | | 类别 | ||
+ | | 目的 | ||
+ | |- | ||
+ | |ftrace | ||
+ | |追踪工具 | ||
+ | |ftrace [1 ](函数跟踪程序)是功能强大的内核跟踪实用程序,例如,它可以跟踪每个内核函数调用和内核事件,而无需在内核源代码中添加任何额外的代码 没有 没有 是 没有 没有 是 | ||
+ | |- | ||
+ | !colspan="3" | STM32MPU嵌入式软件发行版 | ||
+ | |- | ||
+ | | 入门资料包 | ||
+ | | 开发者资料包 | ||
+ | | 发行版资料包 | ||
+ | |- | ||
+ | |没有 | ||
+ | |没有 | ||
+ | |是 | ||
+ | |- | ||
+ | !colspan="3" | 适用于 Android 的STM32MPU嵌入式软件发行版 | ||
+ | |- | ||
+ | | 入门资料包 | ||
+ | | 开发者资料包 | ||
+ | | 发行版资料包 | ||
+ | |- | ||
+ | |没有 | ||
+ | |没有 | ||
+ | |是 | ||
+ | |} | ||
+ | |||
+ | : 注意:在Linux内核4.1之前,所有ftrace跟踪控制文件都在debugfs文件系统中,该文件系统通常位于 /sys/kernel/debug/tracing 中。现在,它位于/ sys/kernel/tracing中,并且独立于debugfs。 | ||
+ | : 为了向后兼容,在安装 debugfs 文件系统时,tracefs 文件系统会自动安装在: /sys/kernel/debug/tracing.。 | ||
+ | |||
+ | : 位于tracefs文件系统中的所有文件也位于该debugfs文件系统目录中。 | ||
+ | |||
+ | : {{redtext|请注意,符号表中存在的所有函数都可用于ftrace。要知道符号列表中是否有可用的函数,可以使用命令 "nm vmlinux | grep <function_name>"}} | ||
+ | |||
+ | ==在目标板上安装跟踪和调试工具== | ||
+ | : ftrace是一项内核功能,在OpenSTLinux发行版中默认情况下未启用,因为这会影响Linux内核大小(vmlinux大约增加1.5%),并且还会对整体性能产生影响,因为其触发了跟踪内核事件和函数调用。 | ||
+ | : 为了使用ftrace所需的“内核功能跟踪程序” ,Linux内核配置必须使用Linux内核menuconfig工具激活 CONFIG_FUNCTION_TRACER 和 CONFIG_FUNCTION_GRAPH_TRACER 配置: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Symbol: FUNCTION_TRACER | ||
+ | Location: | ||
+ | Kernel Hacking ---> | ||
+ | Tracers --> | ||
+ | [*] Kernel Function Tracer | ||
+ | |||
+ | Symbol: FUNCTION_GRAPH_TRACER | ||
+ | Location: | ||
+ | Kernel Hacking ---> | ||
+ | Tracers --> | ||
+ | [*] Kernel Function Tracer | ||
+ | [*] Kernel Function Graph Tracer | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===使用STM32MPU嵌入式软件发行版=== | ||
+ | ====开发人员软件包==== | ||
+ | : 不建议使用Developer Package启用ftrace内核配置,因为所有外部模块需要重新编译(例如GPU STM32MP1的gcnano驱动程序),而Developer Package则无法实现,因为它不需要提供所有资料来源。 | ||
+ | : 这就是为什么将此设置为“开发人员包”不支持的原因。 | ||
+ | |||
+ | ====分发包==== | ||
+ | : 启用所需的Linux内核配置 | ||
+ | : 要在Linux内核配置中启用CONFIG_FUNCTION_TRACER和CONFIG_FUNCTION_GRAPH_TRACER,请参阅 [https://wiki.st.com/stm32mpu/wiki/Menuconfig_or_how_to_configure_kernel Menuconfig或如何配置内核] 一文,以获取有关在Distribution Package上下文中修改配置和重新编译Linux内核镜像的说明。 | ||
+ | : 还必须重新编译不属于Linux内核源代码树的外部Linux内核模块(如果存在)。 | ||
+ | : GPU STM32MP1的gcnano驱动程序示例: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | PC $> bitbake gcnano-driver-stm32mp | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 重新构建完整的OpenSTLinux镜像,以便重新编译所有依赖项并具有正确的rootfs(包括外部Linux内核模块) | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | PC $> bitbake st-image-weston | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 注意:如前所述,启用ftrace配置时,未压缩的Linux内核镜像的大小会增加。 | ||
+ | : 根据目标板的内存配置(在设备树中定义),内核镜像的增加可能与放置在其后的某些保留区域重叠。 | ||
+ | : 在这种情况下,突出显示了编译错误。 | ||
+ | : 如果此重叠影响很小(意味着某些功能不再起作用,但并不关键),则可以通过使用Linux内核Menuconfig工具(Menuconfig或如何配置内核)激活Linux内核配置CONFIG_SECTION_MISMATCH_WARN_ONLY来避免编译错误。) | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Symbol: SECTION_MISMATCH_WARN_ONLY | ||
+ | Location: | ||
+ | Kernel Hacking ---> | ||
+ | Compile-time checks and compiler options --> | ||
+ | [*] Make section mismatch errors non-fatal | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===使用适用于 Android 的 STM32MPU 嵌入式软件发行版=== | ||
+ | ====分发包==== | ||
+ | : 启用所需的Linux内核配置 | ||
+ | : 要在Linux内核配置中启用CONFIG_FUNCTION_TRACER和CONFIG_FUNCTION_GRAPH_TRACER,请参阅[https://wiki.st.com/stm32mpu/wiki/How_to_customize_kernel_for_Android 如何为Android定制内核] 一文,以获取有关修改配置的说明 | ||
+ | : 在Android分发包中重新编译Linux内核镜像和模块。 | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | PC $> build_kernel vmlinux -i | ||
+ | PC $> build_kernel modules -i | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 还必须重新编译不属于Linux内核源代码树的外部Linux内核模块(如果存在的话)。 | ||
+ | GPU STM32MP1的gcnano驱动程序示例: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | PC $> build_kernel gpu -i | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 重建完整的Android镜像,以便重新编译所有依赖关系并考虑Linux内核镜像和模块的新的预构建镜像: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | PC $> make -j | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 注意:如前所述,启用ftrace配置时,未压缩的Linux内核镜像的大小会增加。 | ||
+ | : 根据目标板的内存配置(在设备树中定义),内核镜像的增加可能会覆盖后面放置的一些保留区域。 | ||
+ | : 在这种情况下,突出显示了编译错误。 | ||
+ | : 如果此重叠影响很小(意味着某些功能不再起作用,但并不关键),则可以通过使用Linux内核Menuconfig工具激活Linux内核配置CONFIG_SECTION_MISMATCH_WARN_ONLY来绕过编译错误(如何为Android定制内核)) | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Symbol: SECTION_MISMATCH_WARN_ONLY | ||
+ | Location: | ||
+ | Kernel Hacking ---> | ||
+ | Compile-time checks and compiler options --> | ||
+ | [*] Make section mismatch errors non-fatal | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==使用入门== | ||
+ | ===在运行时使用ftrace=== | ||
+ | : 首先,你需要从目标启用/激活 ftrace 功能。 | ||
+ | |||
+ | : 目标启动并登录后,安装 tracefs: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> mount -t tracefs nodev /sys/kernel/tracing | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 注意:以下信息与 Android 发行版有关 | ||
+ | :: 需要启用root访问权限 | ||
+ | :: 使用ADB Shell可以使用ADB链接: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | PC $> adb root | ||
+ | PC $> adb shell | ||
+ | Board $> ... | ||
+ | </syntaxhighlight> | ||
+ | :: 使用UART控制台shell: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> su | ||
+ | Board $> ... | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 在那一步,所有的"ftrace”功能都发生在文件系统目录路径 /sys/kernel/tracing 中。 | ||
+ | : 要找出可用的跟踪器,只需在跟踪目录中放置 available_tracers 文件即可: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> cat /sys/kernel/tracing/available_tracers | ||
+ | function_graph function nop | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 内核构建配置可以添加更多的跟踪器。请参阅 深入学习 一节。 | ||
+ | |||
+ | ===过滤器选项=== | ||
+ | : 注意:{{redtext|ftrace使用函数/ graph_function过滤器,而不是驱动程序过滤器。因此,跟踪* myDriver *函数不会从myDriver跟踪myHelper函数。}} | ||
+ | : 你可以使用以下命令获取可用的过滤器功能的列表: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> cat /sys/kernel/tracing/available_filter_functions | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ====功能跟踪器模式==== | ||
+ | : 开始跟踪会话 | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> echo 1 > /sys/kernel/tracing/tracing_on | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 要启用函数跟踪器,只需将函数写入 current_tracer 文件。然后,你可以验证当前值: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> echo function > /sys/kernel/tracing/current_tracer | ||
+ | Board $> cat /sys/kernel/tracing/current_tracer | ||
+ | function | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> cat /sys/kernel/tracing/trace | head -20 | ||
+ | # tracer: function | ||
+ | # | ||
+ | # entries-in-buffer/entries-written: 144045/33695515 #P:2 | ||
+ | # | ||
+ | # _-----=> irqs-off | ||
+ | # / _----=> need-resched | ||
+ | # | / _---=> hardirq/softirq | ||
+ | # || / _--=> preempt-depth | ||
+ | # ||| / delay | ||
+ | # TASK-PID CPU# |||| TIMESTAMP FUNCTION | ||
+ | # | | | |||| | | | ||
+ | date-3591 [001] ...3 3278.796042: memblock_is_map_memory <-pfn_valid | ||
+ | date-3591 [001] ...3 3278.796046: unlock_page <-filemap_map_pages | ||
+ | date-3591 [001] ...3 3278.796051: alloc_set_pte <-filemap_map_pages | ||
+ | date-3591 [001] ...3 3278.796053: add_mm_counter_fast <-alloc_set_pte | ||
+ | date-3591 [001] ...3 3278.796055: page_add_file_rmap <-alloc_set_pte | ||
+ | date-3591 [001] ...3 3278.796057: __sync_icache_dcache <-alloc_set_pte | ||
+ | date-3591 [001] ...3 3278.796059: pfn_valid <-__sync_icache_dcache | ||
+ | date-3591 [001] ...3 3278.796061: memblock_is_map_memory <-pfn_valid | ||
+ | date-3591 [001] ...3 3278.796064: unlock_page <-filemap_map_pages | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 要应用功能过滤器,你可以在 /sys/kernel/tracing/set_ftrace_filter 中设置值,然后检查跟踪的新内容: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | # Here we take the example with all uart functions | ||
+ | Board $> echo "*uart*" > /sys/kernel/tracing/set_ftrace_filter | ||
+ | |||
+ | # Clean the existing trace | ||
+ | Board $> echo > /sys/kernel/tracing/trace | ||
+ | |||
+ | # Display new trace content (in that case, please do some actions in the console to get some traces) | ||
+ | Board $> cat /sys/kernel/tracing/trace | head -20 | ||
+ | # tracer: function | ||
+ | # | ||
+ | # _-----=> irqs-off | ||
+ | # / _----=> need-resched | ||
+ | # | / _---=> hardirq/softirq | ||
+ | # || / _--=> preempt-depth | ||
+ | # ||| / delay | ||
+ | # TASK-PID CPU# |||| TIMESTAMP FUNCTION | ||
+ | # | | | |||| | | | ||
+ | sh-343 [000] .... 9313.041827: uart_ioctl <-tty_ioctl | ||
+ | sh-343 [000] .... 9313.041855: uart_ioctl <-tty_ioctl | ||
+ | sh-343 [000] .... 9313.041866: uart_chars_in_buffer <-tty_wait_until_sent | ||
+ | sh-343 [000] .... 9313.041870: uart_wait_until_sent <-tty_wait_until_sent | ||
+ | sh-343 [000] .... 9313.041875: uart_set_termios <-tty_set_termios | ||
+ | sh-343 [000] .... 9313.041968: uart_write_room <-tty_write_room | ||
+ | sh-343 [000] .... 9313.041974: uart_write <-n_tty_write | ||
+ | sh-343 [000] d..1 9313.041979: __uart_start <-uart_write | ||
+ | sh-343 [000] d..1 9313.041987: uart_write_wakeup <-stm32_transmit_chars | ||
+ | sh-343 [000] d.h2 9313.042007: uart_write_wakeup <-stm32_transmit_chars | ||
+ | sh-343 [000] d.h2 9313.042022: uart_write_wakeup <-stm32_transmit_chars | ||
+ | </syntaxhighlight> | ||
+ | : Linux文档ftrace [2 ]中提供了有关过滤选项和配置的更多信息。 | ||
+ | |||
+ | : 要清空跟踪,请参阅段落 "擦除跟踪” | ||
+ | : 要清除过滤器,以便再次记录所有功能: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> echo > /sys/kernel/tracing/set_ftrace_filter | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ====图形功能跟踪器模式==== | ||
+ | : 开始跟踪会话: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> echo 1 > /sys/kernel/tracing/tracing_on | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 要启用功能跟踪器,只需将function_graph写入current_tracer文件。然后,你可以验证当前值: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> echo function_graph > /sys/kernel/tracing/current_tracer | ||
+ | Board $> cat /sys/kernel/tracing/current_tracer | ||
+ | function_graph | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> cat /sys/kernel/tracing/trace | head -20 | ||
+ | # tracer: function_graph | ||
+ | # | ||
+ | # CPU DURATION FUNCTION CALLS | ||
+ | # | | | | | | | | ||
+ | 1) 1.015 us | _spin_lock_irqsave(); | ||
+ | 1) 0.476 us | internal_add_timer(); | ||
+ | 1) 0.423 us | wake_up_idle_cpu(); | ||
+ | 1) 0.461 us | _spin_unlock_irqrestore(); | ||
+ | 1) 4.770 us | } | ||
+ | 1) 5.725 us | } | ||
+ | 1) 0.450 us | mutex_unlock(); | ||
+ | 1) + 24.243 us | } | ||
+ | 1) 0.483 us | _spin_lock_irq(); | ||
+ | 1) 0.517 us | _spin_unlock_irq(); | ||
+ | 1) | prepare_to_wait() { | ||
+ | 1) 0.468 us | _spin_lock_irqsave(); | ||
+ | 1) 0.502 us | _spin_unlock_irqrestore(); | ||
+ | 1) 2.411 us | } | ||
+ | 1) 0.449 us | kthread_should_stop(); | ||
+ | 1) | schedule() { | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 要应用图形函数过滤器,可以在 /sys/kernel/tracing/set_graph_function 中设置值,然后检查跟踪的新内容: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | # Here we take the example with all uart functions | ||
+ | Board $> echo "*uart*" > /sys/kernel/tracing/set_graph_function | ||
+ | |||
+ | # Clean the existing trace | ||
+ | Board $> echo > /sys/kernel/tracing/trace | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | <syntaxhighlight lang="bash"> | ||
+ | # Display the new trace content (in that case, please do some action in the console to get some traces) | ||
+ | Board $> cat /sys/kernel/tracing/trace | head -20 | ||
+ | # tracer: function_graph | ||
+ | # | ||
+ | # CPU DURATION FUNCTION CALLS | ||
+ | # | | | | | | | | ||
+ | 1) | uart_ioctl() { | ||
+ | 1) 0.875 us | mutex_lock(); | ||
+ | 1) 0.792 us | mutex_unlock(); | ||
+ | 1) + 15.542 us | } | ||
+ | 1) | uart_ioctl() { | ||
+ | 1) 0.583 us | mutex_lock(); | ||
+ | 1) 0.584 us | mutex_unlock(); | ||
+ | 1) 9.792 us | } | ||
+ | 1) | uart_chars_in_buffer() { | ||
+ | 1) | _raw_spin_lock_irqsave() { | ||
+ | 1) 0.667 us | preempt_count_add(); | ||
+ | 1) 5.458 us | } | ||
+ | 1) | _raw_spin_unlock_irqrestore() { | ||
+ | 1) 0.583 us | preempt_count_sub(); | ||
+ | 1) 5.000 us | } | ||
+ | 1) + 19.459 us | } | ||
+ | 1) 1.541 us | uart_wait_until_sent(); | ||
+ | 1) | uart_set_termios() { | ||
+ | 1) 0.583 us | mutex_lock(); | ||
+ | 1) 0.583 us | mutex_unlock(); | ||
+ | 1) + 10.291 us | } | ||
+ | 1) | uart_write_room() { | ||
+ | 1) | _raw_spin_lock_irqsave() { | ||
+ | 1) 0.666 us | preempt_count_add(); | ||
+ | 1) 5.333 us | } | ||
+ | 1) | _raw_spin_unlock_irqrestore() { | ||
+ | 1) 0.583 us | preempt_count_sub(); | ||
+ | 1) 5.000 us | } | ||
+ | 1) + 19.625 us | } | ||
+ | 1) | uart_write() { | ||
+ | 1) | _raw_spin_lock_irqsave() { | ||
+ | 1) 0.625 us | preempt_count_add(); | ||
+ | 1) 5.209 us | } | ||
+ | 1) | __uart_start() { | ||
+ | 1) | stm32_start_tx() { | ||
+ | 1) | stm32_transmit_chars() { | ||
+ | </syntaxhighlight> | ||
+ | : 有关ftrace [2 ]的Linux文档,有关过滤选项和配置的更多信息。 | ||
+ | |||
+ | : 要清空跟踪,请参阅段落 "擦除跟踪” | ||
+ | : 要清除此特殊过滤器,以便再次记录所有功能: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> echo > /sys/kernel/tracing/set_graph_function | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===缓冲区大小=== | ||
+ | : 为每个CPU分配一个缓冲区。为了进行跟踪分析,你可以更改此缓冲区的大小(增加或减少)。 | ||
+ | |||
+ | : 可以读取每个CPU的给定大小值,或总计(值以千字节为单位): | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | # Per CPU | ||
+ | Board $> cat /sys/kernel/tracing/buffer_size_kb | ||
+ | 1411 | ||
+ | or | ||
+ | Board $> cat /sys/kernel/tracing/per_cpu/cpuX/buffer_size_kb | ||
+ | 1411 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | <syntaxhighlight lang="bash"> | ||
+ | # Total for all CPUs: combined size of all the trace buffers | ||
+ | Board $> cat /sys/kernel/tracing/buffer_total_size_kb | ||
+ | 2822 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 要更改该值({{redtext|请注意,跟踪缓冲区是在页面中分配的(内核用于分配的你存块,通常大小为4 KB)}}) | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | # Same value for each CPU (here 1000*4096/1024=4000) | ||
+ | Board $> echo 4000 > /sys/kernel/tracing/buffer_size_kb | ||
+ | or | ||
+ | # Change buffer size value for a specific CPU X (here 1000*4096/1024=4000) | ||
+ | Board $> echo 4000 > /sys/kernel/tracing/per_cpu/cpuX/buffer_size_kb | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===在启动时使用ftrace=== | ||
+ | : 你可以从内核启动中使用ftrace,这对于调试启动问题非常有用。 | ||
+ | |||
+ | : 为此,你必须使用内核命令行参数: | ||
+ | :: - 如果要添加过滤器,则可选 {{redtext|ftrace}}以及{{redtext|ftrace_filter}}或{{redtext|ftrace_graph_filter}}。 | ||
+ | |||
+ | ====使用STM32MPU嵌入式软件包==== | ||
+ | : 例如,要修改内核bootargs,可以通过以下方式进行: | ||
+ | |||
+ | :: 从Linux内核控制台挂载引导分区,然后使用vi编辑器更新extlinux.conf文件(请参见手册页[3 ]或简介页[4 ])。例如: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> mount /dev/mmcblk0p4 /boot | ||
+ | # As example for SDCard boot on STM32MP15 Evaluation board, otherwise /boot/<bootdevice>_<platform>-<boardId>_extlinux/extlinux.conf | ||
+ | Board $> vi /boot/mmc0_stm32mp157c-ev1_extlinux/extlinux.conf | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | :: 通过添加ftrace参数来更新内核命令行: | ||
+ | ::: - 功能跟踪器模式 | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | root=/dev/mmcblk0p5 rootwait rw console=ttyS3,115200 ftrace=function ftrace_filter=*uart* | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | ::: - function_graph追踪模式 | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | root=/dev/mmcblk0p5 rootwait rw console=ttyS3,115200 ftrace=function_graph ftrace_graph_filter=*uart* | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | :: 保存并退出文件更新,然后重新启动主板 | ||
+ | :: 或者 | ||
+ | :: 编辑来自microSD?卡的extlinux.conf文件(如果用作引导设备) | ||
+ | |||
+ | : 注意:需要管理员权限 | ||
+ | :: -将microSD卡插入主机PC | ||
+ | :: -检查是否安装了引导分区(即 /media/$USER/bootfs) | ||
+ | :: -编辑与你的设置相对应的extlinux文件(即 /media/$USER/bootfs/mmc0_stm32mp157c-ev1_extlinux/extlinux.conf) | ||
+ | :: -按照所需的ftrace跟踪器配置修改命令行(请参见上文) | ||
+ | :: -保存修改,然后将microSD卡插入目标 | ||
+ | :: -引导并检查内核命令行 | ||
+ | |||
+ | ====使用适用于Android的STM32MPU嵌入式软件包==== | ||
+ | : 例如,要修改内核bootargs,可以通过以下方式来完成,这需要重建启动镜像: | ||
+ | |||
+ | : 编辑文件 device/stm/<STM32Series>/<BoardId>/Boardconfig.mk | ||
+ | : 通过在BOARD_KERNEL_CMDLINE变量中添加ftrace参数来更新内核命令行: | ||
+ | :: - 功能跟踪器模式 | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | ... | ||
+ | # =========================================================== # | ||
+ | # Kernel command line # | ||
+ | # =========================================================== # | ||
+ | BOARD_KERNEL_CMDLINE := console=ttySTM0,115200 androidboot.console=/dev/ttySTM0 consoleblank=0 earlyprintk | ||
+ | BOARD_KERNEL_CMDLINE += skip_initramfs ro rootfstype=ext4 rootwait | ||
+ | BOARD_KERNEL_CMDLINE += init=/init firmware_class.path=/vendor/firmware | ||
+ | BOARD_KERNEL_CMDLINE += androidboot.hardware=stm | ||
+ | BOARD_KERNEL_CMDLINE += ftrace=function ftrace_filter=*uart* | ||
+ | ... | ||
+ | </syntaxhighlight> | ||
+ | :: - function_graph追踪模式 | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | ... | ||
+ | # =========================================================== # | ||
+ | # Kernel command line # | ||
+ | # =========================================================== # | ||
+ | BOARD_KERNEL_CMDLINE := console=ttySTM0,115200 androidboot.console=/dev/ttySTM0 consoleblank=0 earlyprintk | ||
+ | BOARD_KERNEL_CMDLINE += skip_initramfs ro rootfstype=ext4 rootwait | ||
+ | BOARD_KERNEL_CMDLINE += init=/init firmware_class.path=/vendor/firmware | ||
+ | BOARD_KERNEL_CMDLINE += androidboot.hardware=stm | ||
+ | BOARD_KERNEL_CMDLINE += ftrace=function_graph ftrace_graph_filter=*uart* | ||
+ | ... | ||
+ | </syntaxhighlight> | ||
+ | : 重建并重新加载启动镜像 | ||
+ | |||
+ | |||
+ | ====检查跟踪==== | ||
+ | : 引导后,要检查跟踪,必须先挂载tracefs: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> mount -t tracefs nodev /sys/kernel/tracing | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 注意:以下信息与 Android 发行版有关 | ||
+ | :: 需要启用root访问权限 | ||
+ | :: 使用ADB Shell可以使用ADB链接: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | PC $> adb root | ||
+ | PC $> adb shell | ||
+ | Board $> ... | ||
+ | </syntaxhighlight> | ||
+ | :: 使用UART控制台shell: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> su | ||
+ | Board $> ... | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 然后查看跟踪内容(即函数跟踪): | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> cat /sys/kernel/tracing/trace | head -20 | ||
+ | # tracer: function | ||
+ | # | ||
+ | # _-----=> irqs-off | ||
+ | # / _----=> need-resched | ||
+ | # | / _---=> hardirq/softirq | ||
+ | # || / _--=> preempt-depth | ||
+ | # ||| / delay | ||
+ | # TASK-PID CPU# |||| TIMESTAMP FUNCTION | ||
+ | # | | | |||| | | | ||
+ | systemd-1 [000] .... 1.087213: uart_register_driver <-usart_init | ||
+ | systemd-1 [000] .... 1.087847: uart_get_rs485_mode <-stm32_serial_probe | ||
+ | systemd-1 [000] .... 1.088436: uart_add_one_port <-stm32_serial_probe | ||
+ | systemd-1 [000] .... 1.098000: uart_parse_options <-stm32_console_setup | ||
+ | systemd-1 [000] .... 1.098007: uart_set_options <-stm32_console_setup | ||
+ | systemd-1 [000] .... 1.098014: uart_get_baud_rate <-stm32_set_termios | ||
+ | systemd-1 [000] d..1 1.098019: uart_update_timeout <-stm32_set_termios | ||
+ | systemd-1 [000] d..1 1.098090: uart_console_write <-stm32_console_write | ||
+ | systemd-1 [000] d..1 1.105231: uart_console_write <-stm32_console_write | ||
+ | systemd-1 [000] d..1 1.114697: uart_console_write <-stm32_console_write | ||
+ | systemd-1 [000] d..1 1.120300: uart_console_write <-stm32_console_write | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ====捕获(从启动)oops到串行控制台==== | ||
+ | : 在启动时启用ftrace的一个有趣的应用程序是通过在内核命令行上放置以下参数来捕获导致不稳定的函数调用: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | root=/dev/mmcblk0p5 rootwait rw console=ttyS3,115200 ftrace=function ftrace_dump_on_oops | ||
+ | </syntaxhighlight> | ||
+ | : 当发生oops时,ftrace缓冲区将自动转储到控制台消息中。 | ||
+ | |||
+ | ===删除痕迹=== | ||
+ | : 使用以下命令可以擦除ftrace的跟踪内容: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> echo > /sys/kernel/tracing/trace | ||
+ | </syntaxhighlight> | ||
+ | ==深入学习== | ||
+ | ===为ftrace添加打印信息=== | ||
+ | : 除了打印Linux内核功能之外,还可以使用trace_printk函数使用ftrace跟踪特定的调试信息。 | ||
+ | : 它可以像printk()一样使用,也可以在任何上下文中使用(中断代码,NMI代码和调度程序代码)。 | ||
+ | : trace_printk不会输出到控制台,但会写入ftrace环形缓冲区,并且可以通过跟踪文件读取。 | ||
+ | |||
+ | : 要使用trace_printk函数,必须在源代码中包含linux/ftrace.h: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | ... | ||
+ | #include <linux/ftrace.h> | ||
+ | ... | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 然后使用trace_printk语法作为printk(请参见以下示例): | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | ... | ||
+ | trace_printk("%s: %d uart_tx_stopped(port) %i\n", __FUNCTION__, __LINE__, uart_tx_stopped(port)); | ||
+ | ... | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===堆栈跟踪=== | ||
+ | : 从内核文档中提取了ftrace [2 ]。 | ||
+ | : 由于内核具有固定大小的堆栈,因此重要的是不要在功能上浪费它。内核开发人员必须知道函数在堆栈上分配了什么。如果它们增加太大的大小,则系统可能处于堆栈溢出的危险中,并且会发生损坏,通常会导致系统死机。 | ||
+ | : 有一些工具可以检查此情况,通常使用中断定期检查其使用情况。但是,如果你可以在每个函数调用中执行检查,这将非常有用。由于ftrace提供了一个函数跟踪程序,因此可以方便地在每次函数调用时检查堆栈大小。这是通过堆栈跟踪器启用的。 | ||
+ | |||
+ | : Linux内核配置选项CONFIG_STACK_TRACER启用ftrace堆栈跟踪功能。 | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Symbol: STACK_TRACER | ||
+ | Location: | ||
+ | Kernel Hacking ---> | ||
+ | Tracers --> | ||
+ | [*] Trace max stack | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 要启用它,请将 '1' 写入 /proc/sys/kernel/stack_tracer_enabled 中。 | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> echo 1 > /proc/sys/kernel/stack_tracer_enabled | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 你还可以通过在内核命令行参数中添加"stacktrace”,在内核命令行中启用它以在启动过程中跟踪内核的堆栈大小。 | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | root =/dev/mmcblk0p5 rootwait读写控制台= ttyS3,115200 stacktrace | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | : 启动后,要检查跟踪,你必须先安装 tracefs,然后显示跟踪内容: | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | Board $> mount -t tracefs nodev /sys/kernel/tracing | ||
+ | |||
+ | Board $> cat /sys/kernel/tracing/stack_max_size | ||
+ | 2928 | ||
+ | |||
+ | Board $> cat /sys/kernel/tracing/stack_trace | ||
+ | Depth Size Location (82 entries) | ||
+ | ----- ---- -------- | ||
+ | 0) 4328 4 __rcu_read_unlock+0x14/0x68 | ||
+ | 1) 4324 180 select_task_rq_fair+0x8ac/0xb7c | ||
+ | 2) 4144 64 try_to_wake_up+0x100/0x3fc | ||
+ | 3) 4080 16 wake_up_process+0x20/0x24 | ||
+ | 4) 4064 24 swake_up_locked.part.0+0x20/0x38 | ||
+ | 5) 4040 24 swake_up+0x38/0x48 | ||
+ | 6) 4016 16 rcu_gp_kthread_wake+0x4c/0x50 | ||
+ | 7) 4000 24 rcu_report_qs_rsp+0x50/0x84 | ||
+ | 8) 3976 120 rcu_report_qs_rnp+0x258/0x2ec | ||
+ | 9) 3856 80 rcu_process_callbacks+0x290/0x43c | ||
+ | 10) 3776 96 __do_softirq+0x12c/0x3ec | ||
+ | 11) 3680 16 irq_exit+0xd0/0x118 | ||
+ | 12) 3664 48 __handle_domain_irq+0x90/0xfc | ||
+ | 13) 3616 40 gic_handle_irq+0x5c/0xa0 | ||
+ | 14) 3576 68 __irq_svc+0x6c/0xa8 | ||
+ | 15) 3508 28 unwind_get_byte+0x20/0x74 | ||
+ | 16) 3480 160 unwind_frame+0x1a8/0x6b0 | ||
+ | 17) 3320 32 walk_stackframe+0x34/0x40 | ||
+ | 18) 3288 56 __save_stack_trace+0xa4/0xa8 | ||
+ | 19) 3232 16 save_stack_trace+0x30/0x34 | ||
+ | 20) 3216 72 create_object+0x120/0x278 | ||
+ | 21) 3144 40 kmemleak_alloc+0x8c/0xd4 | ||
+ | 22) 3104 64 kmem_cache_alloc+0x184/0x2f0 | ||
+ | 23) 3040 64 __kernfs_new_node+0x58/0x15c | ||
+ | 24) 2976 24 kernfs_new_node+0x2c/0x48 | ||
+ | 25) 2952 24 __kernfs_create_file+0x28/0xb8 | ||
+ | 26) 2928 56 sysfs_add_file_mode_ns+0xc4/0x1a0 | ||
+ | 27) 2872 24 sysfs_create_file_ns+0x4c/0x58 | ||
+ | 28) 2848 56 kobject_add_internal+0x174/0x358 | ||
+ | 29) 2792 40 kobject_add+0x50/0x98 | ||
+ | 30) 2752 32 irq_sysfs_add+0x44/0x60 | ||
+ | 31) 2720 72 __irq_alloc_descs+0x174/0x234 | ||
+ | 32) 2648 48 irq_domain_alloc_descs+0x64/0xe4 | ||
+ | 33) 2600 56 irq_create_mapping+0x108/0x1fc | ||
+ | 34) 2544 56 irq_create_fwspec_mapping+0x140/0x318 | ||
+ | 35) 2488 88 irq_create_of_mapping+0x5c/0x64 | ||
+ | 36) 2400 168 of_irq_get+0x68/0x78 | ||
+ | 37) 2232 24 stpmu1_regulator_parse_dt+0x68/0x80 | ||
+ | 38) 2208 96 regulator_register+0x218/0x970 | ||
+ | 39) 2112 32 devm_regulator_register+0x54/0x84 | ||
+ | 40) 2080 136 stpmu1_regulator_probe+0x350/0x5f4 | ||
+ | 41) 1944 32 platform_drv_probe+0x60/0xbc | ||
+ | 42) 1912 64 driver_probe_device+0x2f4/0x488 | ||
+ | 43) 1848 32 __device_attach_driver+0xac/0x14c | ||
+ | 44) 1816 40 bus_for_each_drv+0x54/0xa4 | ||
+ | 45) 1776 40 __device_attach+0xc0/0x150 | ||
+ | 46) 1736 16 device_initial_probe+0x1c/0x20 | ||
+ | 47) 1720 32 bus_probe_device+0x94/0x9c | ||
+ | 48) 1688 64 device_add+0x3c0/0x5d0 | ||
+ | 49) 1624 16 of_device_add+0x44/0x4c | ||
+ | 50) 1608 40 of_platform_device_create_pdata+0x84/0xb4 | ||
+ | 51) 1568 104 of_platform_bus_create+0x160/0x2f8 | ||
+ | 52) 1464 56 of_platform_populate+0x9c/0x134 | ||
+ | 53) 1408 32 stpmu1_probe+0x6c/0xac | ||
+ | 54) 1376 40 i2c_device_probe+0x290/0x2dc | ||
+ | 55) 1336 64 driver_probe_device+0x2f4/0x488 | ||
+ | 56) 1272 32 __device_attach_driver+0xac/0x14c | ||
+ | 57) 1240 40 bus_for_each_drv+0x54/0xa4 | ||
+ | 58) 1200 40 __device_attach+0xc0/0x150 | ||
+ | 59) 1160 16 device_initial_probe+0x1c/0x20 | ||
+ | 60) 1144 32 bus_probe_device+0x94/0x9c | ||
+ | 61) 1112 64 device_add+0x3c0/0x5d0 | ||
+ | 62) 1048 24 device_register+0x24/0x28 | ||
+ | 63) 1024 48 i2c_new_device+0x14c/0x2f4 | ||
+ | 64) 976 96 of_i2c_register_device+0x134/0x1dc | ||
+ | 65) 880 40 of_i2c_register_devices+0x8c/0x100 | ||
+ | 66) 840 48 i2c_register_adapter+0x184/0x404 | ||
+ | 67) 792 48 i2c_add_adapter+0xa4/0x138 | ||
+ | 68) 744 160 stm32f7_i2c_probe+0x954/0xd08 | ||
+ | 69) 584 32 platform_drv_probe+0x60/0xbc | ||
+ | 70) 552 64 driver_probe_device+0x2f4/0x488 | ||
+ | 71) 488 32 __driver_attach+0x110/0x12c | ||
+ | 72) 456 40 bus_for_each_dev+0x5c/0xac | ||
+ | 73) 416 16 driver_attach+0x2c/0x30 | ||
+ | 74) 400 48 bus_add_driver+0x1d0/0x274 | ||
+ | 75) 352 24 driver_register+0x88/0x104 | ||
+ | 76) 328 16 __platform_driver_register+0x50/0x58 | ||
+ | 77) 312 16 stm32f7_i2c_driver_init+0x24/0x28 | ||
+ | 78) 296 112 do_one_initcall+0x54/0x178 | ||
+ | 79) 184 72 kernel_init_freeable+0x1dc/0x274 | ||
+ | 80) 112 24 kernel_init+0x18/0x124 | ||
+ | 81) 88 88 ret_from_fork+0x14/0x24 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===更多示踪剂=== | ||
+ | : 更多跟踪器可用于ftrace。请参阅Linux内核文档中的ftrace [2 ]。 | ||
+ | {| class="wikitable" | ||
+ | |- | ||
+ | ! 跟踪器名称 !! 描述 | ||
+ | |- | ||
+ | |blk || 块跟踪器。blktrace用户应用程序 使用的跟踪器 | ||
+ | |- | ||
+ | |hwlat || 硬件延迟跟踪器。它用于检测硬件是否产生任何延迟 | ||
+ | |- | ||
+ | |irqsoff || 跟踪禁用中断的区域,并以最长的最大延迟保存跟踪 | ||
+ | |- | ||
+ | |preemptoff || 与irqsoff类似,但跟踪并记录禁用抢占的时间 | ||
+ | |- | ||
+ | |preemptirqsoff || 与irqsoff和preemptoff类似,但是跟踪并记录禁用irqs和/或抢占的最大时间 | ||
+ | |- | ||
+ | |wakeup || 跟踪并记录唤醒后优先级最高的任务安排所需的最大延迟 | ||
+ | |- | ||
+ | |wakeup_rt || 跟踪并记录仅RT任务所需的最大延迟(就像当前的“唤醒”一样) | ||
+ | |- | ||
+ | |wakeup_dl || 跟踪并记录唤醒SCHED_DEADLINE任务所需的最大延迟(如"wakeup”和"wakeup_rt”一样) | ||
+ | |- | ||
+ | |mmiotrace || 一种特殊的跟踪器,用于跟踪二进制模块。它跟踪模块对硬件的所有调用 | ||
+ | |- | ||
+ | |branch || 在跟踪内核中可能/不太可能发生的调用时可以配置此跟踪器 | ||
+ | |- | ||
+ | |nop || 这是“空的”追踪器 | ||
+ | |} | ||
+ | |||
+ | ===辅助工具=== | ||
+ | : 尽管 [https://wiki.st.com/stm32mpu/wiki/Debugfs debugfs] 接口非常简单,但使用起来也很尴尬。建议使用一些工具来简化ftrace的用户体验。 | ||
+ | * [https://wiki.st.com/stm32mpu/wiki/Trace-cmd_and_kernelshark_trace_viewer trace-cmd命令行阅读器和kernelshark跟踪查看器] | ||
+ | :: trace-cmd是一种命令行工具,可以与ftrace配合使用并与之交互,而不是将命令回显到特定文件中并从另一个文件读取结果。它提出了一个高级用户命令界面来简化ftrace的使用。 | ||
+ | :: 与trace-cmd相关联的kernelshark工具提出了一个跟踪查看器,可用于分析跟踪。 | ||
+ | * [https://wiki.st.com/stm32mpu/wiki/LTTng Linux跟踪工具套件(LTTng)和Trace Compass查看器] | ||
+ | :: LTTng是部分基于ftrace的Linux开源跟踪框架,该框架还通过命令行提出了高级用户界面。我们将主机PC端的Trace Compass与日志查看器关联。 | ||
+ | |||
+ | ==参考== | ||
+ | * 1. [https://elinux.org/Ftrace https://elinux.org/Ftrace] | ||
+ | * 2. [https://github.com/STMicroelectronics/linux/blob/v4.19-stm32mp/Documentation/trace/ftrace.rst Documentation/trace/ftrace.rst] | ||
+ | * 3. [http://ex-vi.sourceforge.net/vi.html http://ex-vi.sourceforge.net/vi.html] | ||
+ | * 4. [http://ex-vi.sourceforge.net/viin/paper.html http://ex-vi.sourceforge.net/viin/paper.html] | ||
+ | |||
+ | * 有用的外部链接 | ||
+ | {| class="wikitable" | ||
+ | |- | ||
+ | ! 文件链接 !! 文件类型 !! 描述 | ||
+ | |- | ||
+ | | [https://www.kernel.org/doc/Documentation/trace/ftrace.txt ftrace(kernel.org文档)] || 标准 || Linux内核来源的文档 | ||
+ | |- | ||
+ | | [http://lwn.net/Articles/365835/ 使用Ftrace调试内核-第1部分] || 用户指南 || [http://lwn.net http://lwn.net] | ||
+ | |- | ||
+ | | [http://lwn.net/Articles/366796/ 使用Ftrace调试内核-第2部分] || 用户指南 || [http://lwn.net http://lwn.net] | ||
+ | |- | ||
+ | | [http://lwn.net/Articles/379903 使用TRACE_EVENT()宏(带有CREATE_TRACE_POINTS)] || 训练 || [http://lwn.net http://lwn.net] | ||
+ | |- | ||
+ | | [https://wiki.linaro.org/WorkingGroups/PowerManagement/Resources/Tools/load-perf-analyses#Using_ftrace 使用ftrace加载性能分析] || 用户指南 || Linaro | ||
+ | |} | ||
+ | |||
[[Category:Linux_Operating_System]] | [[Category:Linux_Operating_System]] | ||
[[Category:Linux_tracing_tools]] | [[Category:Linux_tracing_tools]] |
2019年12月26日 (四) 16:05的最新版本
Ftrace
文章目的
- 本文提供了开始使用Linux内核工具所需的基本信息:ftrace [1 ]。
简介
- 下表简要介绍了该工具及其可用性,具体取决于软件包:
- 是:该工具已经存在(可以使用或激活),也可以在软件包中集成和激活。
- 没有:该工具不存在且无法集成,或者存在但无法在软件包中激活。
工具 | ||
---|---|---|
名称 | 类别 | 目的 |
ftrace | 追踪工具 | ftrace [1 ](函数跟踪程序)是功能强大的内核跟踪实用程序,例如,它可以跟踪每个内核函数调用和内核事件,而无需在内核源代码中添加任何额外的代码 没有 没有 是 没有 没有 是 |
STM32MPU嵌入式软件发行版 | ||
入门资料包 | 开发者资料包 | 发行版资料包 |
没有 | 没有 | 是 |
适用于 Android 的STM32MPU嵌入式软件发行版 | ||
入门资料包 | 开发者资料包 | 发行版资料包 |
没有 | 没有 | 是 |
- 注意:在Linux内核4.1之前,所有ftrace跟踪控制文件都在debugfs文件系统中,该文件系统通常位于 /sys/kernel/debug/tracing 中。现在,它位于/ sys/kernel/tracing中,并且独立于debugfs。
- 为了向后兼容,在安装 debugfs 文件系统时,tracefs 文件系统会自动安装在: /sys/kernel/debug/tracing.。
- 位于tracefs文件系统中的所有文件也位于该debugfs文件系统目录中。
- 请注意,符号表中存在的所有函数都可用于ftrace。要知道符号列表中是否有可用的函数,可以使用命令 "nm vmlinux
在目标板上安装跟踪和调试工具
- ftrace是一项内核功能,在OpenSTLinux发行版中默认情况下未启用,因为这会影响Linux内核大小(vmlinux大约增加1.5%),并且还会对整体性能产生影响,因为其触发了跟踪内核事件和函数调用。
- 为了使用ftrace所需的“内核功能跟踪程序” ,Linux内核配置必须使用Linux内核menuconfig工具激活 CONFIG_FUNCTION_TRACER 和 CONFIG_FUNCTION_GRAPH_TRACER 配置:
Symbol: FUNCTION_TRACER
Location:
Kernel Hacking --->
Tracers -->
[*] Kernel Function Tracer
Symbol: FUNCTION_GRAPH_TRACER
Location:
Kernel Hacking --->
Tracers -->
[*] Kernel Function Tracer
[*] Kernel Function Graph Tracer
使用STM32MPU嵌入式软件发行版
开发人员软件包
- 不建议使用Developer Package启用ftrace内核配置,因为所有外部模块需要重新编译(例如GPU STM32MP1的gcnano驱动程序),而Developer Package则无法实现,因为它不需要提供所有资料来源。
- 这就是为什么将此设置为“开发人员包”不支持的原因。
分发包
- 启用所需的Linux内核配置
- 要在Linux内核配置中启用CONFIG_FUNCTION_TRACER和CONFIG_FUNCTION_GRAPH_TRACER,请参阅 Menuconfig或如何配置内核 一文,以获取有关在Distribution Package上下文中修改配置和重新编译Linux内核镜像的说明。
- 还必须重新编译不属于Linux内核源代码树的外部Linux内核模块(如果存在)。
- GPU STM32MP1的gcnano驱动程序示例:
PC $> bitbake gcnano-driver-stm32mp
- 重新构建完整的OpenSTLinux镜像,以便重新编译所有依赖项并具有正确的rootfs(包括外部Linux内核模块)
PC $> bitbake st-image-weston
- 注意:如前所述,启用ftrace配置时,未压缩的Linux内核镜像的大小会增加。
- 根据目标板的内存配置(在设备树中定义),内核镜像的增加可能与放置在其后的某些保留区域重叠。
- 在这种情况下,突出显示了编译错误。
- 如果此重叠影响很小(意味着某些功能不再起作用,但并不关键),则可以通过使用Linux内核Menuconfig工具(Menuconfig或如何配置内核)激活Linux内核配置CONFIG_SECTION_MISMATCH_WARN_ONLY来避免编译错误。)
Symbol: SECTION_MISMATCH_WARN_ONLY
Location:
Kernel Hacking --->
Compile-time checks and compiler options -->
[*] Make section mismatch errors non-fatal
使用适用于 Android 的 STM32MPU 嵌入式软件发行版
分发包
- 启用所需的Linux内核配置
- 要在Linux内核配置中启用CONFIG_FUNCTION_TRACER和CONFIG_FUNCTION_GRAPH_TRACER,请参阅如何为Android定制内核 一文,以获取有关修改配置的说明
- 在Android分发包中重新编译Linux内核镜像和模块。
PC $> build_kernel vmlinux -i
PC $> build_kernel modules -i
- 还必须重新编译不属于Linux内核源代码树的外部Linux内核模块(如果存在的话)。
GPU STM32MP1的gcnano驱动程序示例:
PC $> build_kernel gpu -i
- 重建完整的Android镜像,以便重新编译所有依赖关系并考虑Linux内核镜像和模块的新的预构建镜像:
PC $> make -j
- 注意:如前所述,启用ftrace配置时,未压缩的Linux内核镜像的大小会增加。
- 根据目标板的内存配置(在设备树中定义),内核镜像的增加可能会覆盖后面放置的一些保留区域。
- 在这种情况下,突出显示了编译错误。
- 如果此重叠影响很小(意味着某些功能不再起作用,但并不关键),则可以通过使用Linux内核Menuconfig工具激活Linux内核配置CONFIG_SECTION_MISMATCH_WARN_ONLY来绕过编译错误(如何为Android定制内核))
Symbol: SECTION_MISMATCH_WARN_ONLY
Location:
Kernel Hacking --->
Compile-time checks and compiler options -->
[*] Make section mismatch errors non-fatal
使用入门
在运行时使用ftrace
- 首先,你需要从目标启用/激活 ftrace 功能。
- 目标启动并登录后,安装 tracefs:
Board $> mount -t tracefs nodev /sys/kernel/tracing
- 注意:以下信息与 Android 发行版有关
- 需要启用root访问权限
- 使用ADB Shell可以使用ADB链接:
PC $> adb root
PC $> adb shell
Board $> ...
- 使用UART控制台shell:
Board $> su
Board $> ...
- 在那一步,所有的"ftrace”功能都发生在文件系统目录路径 /sys/kernel/tracing 中。
- 要找出可用的跟踪器,只需在跟踪目录中放置 available_tracers 文件即可:
Board $> cat /sys/kernel/tracing/available_tracers
function_graph function nop
- 内核构建配置可以添加更多的跟踪器。请参阅 深入学习 一节。
过滤器选项
- 注意:ftrace使用函数/ graph_function过滤器,而不是驱动程序过滤器。因此,跟踪* myDriver *函数不会从myDriver跟踪myHelper函数。
- 你可以使用以下命令获取可用的过滤器功能的列表:
Board $> cat /sys/kernel/tracing/available_filter_functions
功能跟踪器模式
- 开始跟踪会话
Board $> echo 1 > /sys/kernel/tracing/tracing_on
- 要启用函数跟踪器,只需将函数写入 current_tracer 文件。然后,你可以验证当前值:
Board $> echo function > /sys/kernel/tracing/current_tracer
Board $> cat /sys/kernel/tracing/current_tracer
function
Board $> cat /sys/kernel/tracing/trace | head -20
# tracer: function
#
# entries-in-buffer/entries-written: 144045/33695515 #P:2
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
date-3591 [001] ...3 3278.796042: memblock_is_map_memory <-pfn_valid
date-3591 [001] ...3 3278.796046: unlock_page <-filemap_map_pages
date-3591 [001] ...3 3278.796051: alloc_set_pte <-filemap_map_pages
date-3591 [001] ...3 3278.796053: add_mm_counter_fast <-alloc_set_pte
date-3591 [001] ...3 3278.796055: page_add_file_rmap <-alloc_set_pte
date-3591 [001] ...3 3278.796057: __sync_icache_dcache <-alloc_set_pte
date-3591 [001] ...3 3278.796059: pfn_valid <-__sync_icache_dcache
date-3591 [001] ...3 3278.796061: memblock_is_map_memory <-pfn_valid
date-3591 [001] ...3 3278.796064: unlock_page <-filemap_map_pages
- 要应用功能过滤器,你可以在 /sys/kernel/tracing/set_ftrace_filter 中设置值,然后检查跟踪的新内容:
# Here we take the example with all uart functions
Board $> echo "*uart*" > /sys/kernel/tracing/set_ftrace_filter
# Clean the existing trace
Board $> echo > /sys/kernel/tracing/trace
# Display new trace content (in that case, please do some actions in the console to get some traces)
Board $> cat /sys/kernel/tracing/trace | head -20
# tracer: function
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
sh-343 [000] .... 9313.041827: uart_ioctl <-tty_ioctl
sh-343 [000] .... 9313.041855: uart_ioctl <-tty_ioctl
sh-343 [000] .... 9313.041866: uart_chars_in_buffer <-tty_wait_until_sent
sh-343 [000] .... 9313.041870: uart_wait_until_sent <-tty_wait_until_sent
sh-343 [000] .... 9313.041875: uart_set_termios <-tty_set_termios
sh-343 [000] .... 9313.041968: uart_write_room <-tty_write_room
sh-343 [000] .... 9313.041974: uart_write <-n_tty_write
sh-343 [000] d..1 9313.041979: __uart_start <-uart_write
sh-343 [000] d..1 9313.041987: uart_write_wakeup <-stm32_transmit_chars
sh-343 [000] d.h2 9313.042007: uart_write_wakeup <-stm32_transmit_chars
sh-343 [000] d.h2 9313.042022: uart_write_wakeup <-stm32_transmit_chars
- Linux文档ftrace [2 ]中提供了有关过滤选项和配置的更多信息。
- 要清空跟踪,请参阅段落 "擦除跟踪”
- 要清除过滤器,以便再次记录所有功能:
Board $> echo > /sys/kernel/tracing/set_ftrace_filter
图形功能跟踪器模式
- 开始跟踪会话:
Board $> echo 1 > /sys/kernel/tracing/tracing_on
- 要启用功能跟踪器,只需将function_graph写入current_tracer文件。然后,你可以验证当前值:
Board $> echo function_graph > /sys/kernel/tracing/current_tracer
Board $> cat /sys/kernel/tracing/current_tracer
function_graph
Board $> cat /sys/kernel/tracing/trace | head -20
# tracer: function_graph
#
# CPU DURATION FUNCTION CALLS
# | | | | | | |
1) 1.015 us | _spin_lock_irqsave();
1) 0.476 us | internal_add_timer();
1) 0.423 us | wake_up_idle_cpu();
1) 0.461 us | _spin_unlock_irqrestore();
1) 4.770 us | }
1) 5.725 us | }
1) 0.450 us | mutex_unlock();
1) + 24.243 us | }
1) 0.483 us | _spin_lock_irq();
1) 0.517 us | _spin_unlock_irq();
1) | prepare_to_wait() {
1) 0.468 us | _spin_lock_irqsave();
1) 0.502 us | _spin_unlock_irqrestore();
1) 2.411 us | }
1) 0.449 us | kthread_should_stop();
1) | schedule() {
- 要应用图形函数过滤器,可以在 /sys/kernel/tracing/set_graph_function 中设置值,然后检查跟踪的新内容:
# Here we take the example with all uart functions
Board $> echo "*uart*" > /sys/kernel/tracing/set_graph_function
# Clean the existing trace
Board $> echo > /sys/kernel/tracing/trace
# Display the new trace content (in that case, please do some action in the console to get some traces)
Board $> cat /sys/kernel/tracing/trace | head -20
# tracer: function_graph
#
# CPU DURATION FUNCTION CALLS
# | | | | | | |
1) | uart_ioctl() {
1) 0.875 us | mutex_lock();
1) 0.792 us | mutex_unlock();
1) + 15.542 us | }
1) | uart_ioctl() {
1) 0.583 us | mutex_lock();
1) 0.584 us | mutex_unlock();
1) 9.792 us | }
1) | uart_chars_in_buffer() {
1) | _raw_spin_lock_irqsave() {
1) 0.667 us | preempt_count_add();
1) 5.458 us | }
1) | _raw_spin_unlock_irqrestore() {
1) 0.583 us | preempt_count_sub();
1) 5.000 us | }
1) + 19.459 us | }
1) 1.541 us | uart_wait_until_sent();
1) | uart_set_termios() {
1) 0.583 us | mutex_lock();
1) 0.583 us | mutex_unlock();
1) + 10.291 us | }
1) | uart_write_room() {
1) | _raw_spin_lock_irqsave() {
1) 0.666 us | preempt_count_add();
1) 5.333 us | }
1) | _raw_spin_unlock_irqrestore() {
1) 0.583 us | preempt_count_sub();
1) 5.000 us | }
1) + 19.625 us | }
1) | uart_write() {
1) | _raw_spin_lock_irqsave() {
1) 0.625 us | preempt_count_add();
1) 5.209 us | }
1) | __uart_start() {
1) | stm32_start_tx() {
1) | stm32_transmit_chars() {
- 有关ftrace [2 ]的Linux文档,有关过滤选项和配置的更多信息。
- 要清空跟踪,请参阅段落 "擦除跟踪”
- 要清除此特殊过滤器,以便再次记录所有功能:
Board $> echo > /sys/kernel/tracing/set_graph_function
缓冲区大小
- 为每个CPU分配一个缓冲区。为了进行跟踪分析,你可以更改此缓冲区的大小(增加或减少)。
- 可以读取每个CPU的给定大小值,或总计(值以千字节为单位):
# Per CPU
Board $> cat /sys/kernel/tracing/buffer_size_kb
1411
or
Board $> cat /sys/kernel/tracing/per_cpu/cpuX/buffer_size_kb
1411
# Total for all CPUs: combined size of all the trace buffers
Board $> cat /sys/kernel/tracing/buffer_total_size_kb
2822
- 要更改该值(请注意,跟踪缓冲区是在页面中分配的(内核用于分配的你存块,通常大小为4 KB))
# Same value for each CPU (here 1000*4096/1024=4000)
Board $> echo 4000 > /sys/kernel/tracing/buffer_size_kb
or
# Change buffer size value for a specific CPU X (here 1000*4096/1024=4000)
Board $> echo 4000 > /sys/kernel/tracing/per_cpu/cpuX/buffer_size_kb
在启动时使用ftrace
- 你可以从内核启动中使用ftrace,这对于调试启动问题非常有用。
- 为此,你必须使用内核命令行参数:
- - 如果要添加过滤器,则可选 ftrace以及ftrace_filter或ftrace_graph_filter。
使用STM32MPU嵌入式软件包
- 例如,要修改内核bootargs,可以通过以下方式进行:
- 从Linux内核控制台挂载引导分区,然后使用vi编辑器更新extlinux.conf文件(请参见手册页[3 ]或简介页[4 ])。例如:
Board $> mount /dev/mmcblk0p4 /boot
# As example for SDCard boot on STM32MP15 Evaluation board, otherwise /boot/<bootdevice>_<platform>-<boardId>_extlinux/extlinux.conf
Board $> vi /boot/mmc0_stm32mp157c-ev1_extlinux/extlinux.conf
- 通过添加ftrace参数来更新内核命令行:
- - 功能跟踪器模式
- 通过添加ftrace参数来更新内核命令行:
root=/dev/mmcblk0p5 rootwait rw console=ttyS3,115200 ftrace=function ftrace_filter=*uart*
- - function_graph追踪模式
root=/dev/mmcblk0p5 rootwait rw console=ttyS3,115200 ftrace=function_graph ftrace_graph_filter=*uart*
- 保存并退出文件更新,然后重新启动主板
- 或者
- 编辑来自microSD?卡的extlinux.conf文件(如果用作引导设备)
- 注意:需要管理员权限
- -将microSD卡插入主机PC
- -检查是否安装了引导分区(即 /media/$USER/bootfs)
- -编辑与你的设置相对应的extlinux文件(即 /media/$USER/bootfs/mmc0_stm32mp157c-ev1_extlinux/extlinux.conf)
- -按照所需的ftrace跟踪器配置修改命令行(请参见上文)
- -保存修改,然后将microSD卡插入目标
- -引导并检查内核命令行
使用适用于Android的STM32MPU嵌入式软件包
- 例如,要修改内核bootargs,可以通过以下方式来完成,这需要重建启动镜像:
- 编辑文件 device/stm/<STM32Series>/<BoardId>/Boardconfig.mk
- 通过在BOARD_KERNEL_CMDLINE变量中添加ftrace参数来更新内核命令行:
- - 功能跟踪器模式
...
# =========================================================== #
# Kernel command line #
# =========================================================== #
BOARD_KERNEL_CMDLINE := console=ttySTM0,115200 androidboot.console=/dev/ttySTM0 consoleblank=0 earlyprintk
BOARD_KERNEL_CMDLINE += skip_initramfs ro rootfstype=ext4 rootwait
BOARD_KERNEL_CMDLINE += init=/init firmware_class.path=/vendor/firmware
BOARD_KERNEL_CMDLINE += androidboot.hardware=stm
BOARD_KERNEL_CMDLINE += ftrace=function ftrace_filter=*uart*
...
- - function_graph追踪模式
...
# =========================================================== #
# Kernel command line #
# =========================================================== #
BOARD_KERNEL_CMDLINE := console=ttySTM0,115200 androidboot.console=/dev/ttySTM0 consoleblank=0 earlyprintk
BOARD_KERNEL_CMDLINE += skip_initramfs ro rootfstype=ext4 rootwait
BOARD_KERNEL_CMDLINE += init=/init firmware_class.path=/vendor/firmware
BOARD_KERNEL_CMDLINE += androidboot.hardware=stm
BOARD_KERNEL_CMDLINE += ftrace=function_graph ftrace_graph_filter=*uart*
...
- 重建并重新加载启动镜像
检查跟踪
- 引导后,要检查跟踪,必须先挂载tracefs:
Board $> mount -t tracefs nodev /sys/kernel/tracing
- 注意:以下信息与 Android 发行版有关
- 需要启用root访问权限
- 使用ADB Shell可以使用ADB链接:
PC $> adb root
PC $> adb shell
Board $> ...
- 使用UART控制台shell:
Board $> su
Board $> ...
- 然后查看跟踪内容(即函数跟踪):
Board $> cat /sys/kernel/tracing/trace | head -20
# tracer: function
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
systemd-1 [000] .... 1.087213: uart_register_driver <-usart_init
systemd-1 [000] .... 1.087847: uart_get_rs485_mode <-stm32_serial_probe
systemd-1 [000] .... 1.088436: uart_add_one_port <-stm32_serial_probe
systemd-1 [000] .... 1.098000: uart_parse_options <-stm32_console_setup
systemd-1 [000] .... 1.098007: uart_set_options <-stm32_console_setup
systemd-1 [000] .... 1.098014: uart_get_baud_rate <-stm32_set_termios
systemd-1 [000] d..1 1.098019: uart_update_timeout <-stm32_set_termios
systemd-1 [000] d..1 1.098090: uart_console_write <-stm32_console_write
systemd-1 [000] d..1 1.105231: uart_console_write <-stm32_console_write
systemd-1 [000] d..1 1.114697: uart_console_write <-stm32_console_write
systemd-1 [000] d..1 1.120300: uart_console_write <-stm32_console_write
捕获(从启动)oops到串行控制台
- 在启动时启用ftrace的一个有趣的应用程序是通过在内核命令行上放置以下参数来捕获导致不稳定的函数调用:
root=/dev/mmcblk0p5 rootwait rw console=ttyS3,115200 ftrace=function ftrace_dump_on_oops
- 当发生oops时,ftrace缓冲区将自动转储到控制台消息中。
删除痕迹
- 使用以下命令可以擦除ftrace的跟踪内容:
Board $> echo > /sys/kernel/tracing/trace
深入学习
为ftrace添加打印信息
- 除了打印Linux内核功能之外,还可以使用trace_printk函数使用ftrace跟踪特定的调试信息。
- 它可以像printk()一样使用,也可以在任何上下文中使用(中断代码,NMI代码和调度程序代码)。
- trace_printk不会输出到控制台,但会写入ftrace环形缓冲区,并且可以通过跟踪文件读取。
- 要使用trace_printk函数,必须在源代码中包含linux/ftrace.h:
...
#include <linux/ftrace.h>
...
- 然后使用trace_printk语法作为printk(请参见以下示例):
...
trace_printk("%s: %d uart_tx_stopped(port) %i\n", __FUNCTION__, __LINE__, uart_tx_stopped(port));
...
堆栈跟踪
- 从内核文档中提取了ftrace [2 ]。
- 由于内核具有固定大小的堆栈,因此重要的是不要在功能上浪费它。内核开发人员必须知道函数在堆栈上分配了什么。如果它们增加太大的大小,则系统可能处于堆栈溢出的危险中,并且会发生损坏,通常会导致系统死机。
- 有一些工具可以检查此情况,通常使用中断定期检查其使用情况。但是,如果你可以在每个函数调用中执行检查,这将非常有用。由于ftrace提供了一个函数跟踪程序,因此可以方便地在每次函数调用时检查堆栈大小。这是通过堆栈跟踪器启用的。
- Linux内核配置选项CONFIG_STACK_TRACER启用ftrace堆栈跟踪功能。
Symbol: STACK_TRACER
Location:
Kernel Hacking --->
Tracers -->
[*] Trace max stack
- 要启用它,请将 '1' 写入 /proc/sys/kernel/stack_tracer_enabled 中。
Board $> echo 1 > /proc/sys/kernel/stack_tracer_enabled
- 你还可以通过在内核命令行参数中添加"stacktrace”,在内核命令行中启用它以在启动过程中跟踪内核的堆栈大小。
root =/dev/mmcblk0p5 rootwait读写控制台= ttyS3,115200 stacktrace
- 启动后,要检查跟踪,你必须先安装 tracefs,然后显示跟踪内容:
Board $> mount -t tracefs nodev /sys/kernel/tracing
Board $> cat /sys/kernel/tracing/stack_max_size
2928
Board $> cat /sys/kernel/tracing/stack_trace
Depth Size Location (82 entries)
----- ---- --------
0) 4328 4 __rcu_read_unlock+0x14/0x68
1) 4324 180 select_task_rq_fair+0x8ac/0xb7c
2) 4144 64 try_to_wake_up+0x100/0x3fc
3) 4080 16 wake_up_process+0x20/0x24
4) 4064 24 swake_up_locked.part.0+0x20/0x38
5) 4040 24 swake_up+0x38/0x48
6) 4016 16 rcu_gp_kthread_wake+0x4c/0x50
7) 4000 24 rcu_report_qs_rsp+0x50/0x84
8) 3976 120 rcu_report_qs_rnp+0x258/0x2ec
9) 3856 80 rcu_process_callbacks+0x290/0x43c
10) 3776 96 __do_softirq+0x12c/0x3ec
11) 3680 16 irq_exit+0xd0/0x118
12) 3664 48 __handle_domain_irq+0x90/0xfc
13) 3616 40 gic_handle_irq+0x5c/0xa0
14) 3576 68 __irq_svc+0x6c/0xa8
15) 3508 28 unwind_get_byte+0x20/0x74
16) 3480 160 unwind_frame+0x1a8/0x6b0
17) 3320 32 walk_stackframe+0x34/0x40
18) 3288 56 __save_stack_trace+0xa4/0xa8
19) 3232 16 save_stack_trace+0x30/0x34
20) 3216 72 create_object+0x120/0x278
21) 3144 40 kmemleak_alloc+0x8c/0xd4
22) 3104 64 kmem_cache_alloc+0x184/0x2f0
23) 3040 64 __kernfs_new_node+0x58/0x15c
24) 2976 24 kernfs_new_node+0x2c/0x48
25) 2952 24 __kernfs_create_file+0x28/0xb8
26) 2928 56 sysfs_add_file_mode_ns+0xc4/0x1a0
27) 2872 24 sysfs_create_file_ns+0x4c/0x58
28) 2848 56 kobject_add_internal+0x174/0x358
29) 2792 40 kobject_add+0x50/0x98
30) 2752 32 irq_sysfs_add+0x44/0x60
31) 2720 72 __irq_alloc_descs+0x174/0x234
32) 2648 48 irq_domain_alloc_descs+0x64/0xe4
33) 2600 56 irq_create_mapping+0x108/0x1fc
34) 2544 56 irq_create_fwspec_mapping+0x140/0x318
35) 2488 88 irq_create_of_mapping+0x5c/0x64
36) 2400 168 of_irq_get+0x68/0x78
37) 2232 24 stpmu1_regulator_parse_dt+0x68/0x80
38) 2208 96 regulator_register+0x218/0x970
39) 2112 32 devm_regulator_register+0x54/0x84
40) 2080 136 stpmu1_regulator_probe+0x350/0x5f4
41) 1944 32 platform_drv_probe+0x60/0xbc
42) 1912 64 driver_probe_device+0x2f4/0x488
43) 1848 32 __device_attach_driver+0xac/0x14c
44) 1816 40 bus_for_each_drv+0x54/0xa4
45) 1776 40 __device_attach+0xc0/0x150
46) 1736 16 device_initial_probe+0x1c/0x20
47) 1720 32 bus_probe_device+0x94/0x9c
48) 1688 64 device_add+0x3c0/0x5d0
49) 1624 16 of_device_add+0x44/0x4c
50) 1608 40 of_platform_device_create_pdata+0x84/0xb4
51) 1568 104 of_platform_bus_create+0x160/0x2f8
52) 1464 56 of_platform_populate+0x9c/0x134
53) 1408 32 stpmu1_probe+0x6c/0xac
54) 1376 40 i2c_device_probe+0x290/0x2dc
55) 1336 64 driver_probe_device+0x2f4/0x488
56) 1272 32 __device_attach_driver+0xac/0x14c
57) 1240 40 bus_for_each_drv+0x54/0xa4
58) 1200 40 __device_attach+0xc0/0x150
59) 1160 16 device_initial_probe+0x1c/0x20
60) 1144 32 bus_probe_device+0x94/0x9c
61) 1112 64 device_add+0x3c0/0x5d0
62) 1048 24 device_register+0x24/0x28
63) 1024 48 i2c_new_device+0x14c/0x2f4
64) 976 96 of_i2c_register_device+0x134/0x1dc
65) 880 40 of_i2c_register_devices+0x8c/0x100
66) 840 48 i2c_register_adapter+0x184/0x404
67) 792 48 i2c_add_adapter+0xa4/0x138
68) 744 160 stm32f7_i2c_probe+0x954/0xd08
69) 584 32 platform_drv_probe+0x60/0xbc
70) 552 64 driver_probe_device+0x2f4/0x488
71) 488 32 __driver_attach+0x110/0x12c
72) 456 40 bus_for_each_dev+0x5c/0xac
73) 416 16 driver_attach+0x2c/0x30
74) 400 48 bus_add_driver+0x1d0/0x274
75) 352 24 driver_register+0x88/0x104
76) 328 16 __platform_driver_register+0x50/0x58
77) 312 16 stm32f7_i2c_driver_init+0x24/0x28
78) 296 112 do_one_initcall+0x54/0x178
79) 184 72 kernel_init_freeable+0x1dc/0x274
80) 112 24 kernel_init+0x18/0x124
81) 88 88 ret_from_fork+0x14/0x24
更多示踪剂
- 更多跟踪器可用于ftrace。请参阅Linux内核文档中的ftrace [2 ]。
跟踪器名称 | 描述 |
---|---|
blk | 块跟踪器。blktrace用户应用程序 使用的跟踪器 |
hwlat | 硬件延迟跟踪器。它用于检测硬件是否产生任何延迟 |
irqsoff | 跟踪禁用中断的区域,并以最长的最大延迟保存跟踪 |
preemptoff | 与irqsoff类似,但跟踪并记录禁用抢占的时间 |
preemptirqsoff | 与irqsoff和preemptoff类似,但是跟踪并记录禁用irqs和/或抢占的最大时间 |
wakeup | 跟踪并记录唤醒后优先级最高的任务安排所需的最大延迟 |
wakeup_rt | 跟踪并记录仅RT任务所需的最大延迟(就像当前的“唤醒”一样) |
wakeup_dl | 跟踪并记录唤醒SCHED_DEADLINE任务所需的最大延迟(如"wakeup”和"wakeup_rt”一样) |
mmiotrace | 一种特殊的跟踪器,用于跟踪二进制模块。它跟踪模块对硬件的所有调用 |
branch | 在跟踪内核中可能/不太可能发生的调用时可以配置此跟踪器 |
nop | 这是“空的”追踪器 |
辅助工具
- 尽管 debugfs 接口非常简单,但使用起来也很尴尬。建议使用一些工具来简化ftrace的用户体验。
- trace-cmd是一种命令行工具,可以与ftrace配合使用并与之交互,而不是将命令回显到特定文件中并从另一个文件读取结果。它提出了一个高级用户命令界面来简化ftrace的使用。
- 与trace-cmd相关联的kernelshark工具提出了一个跟踪查看器,可用于分析跟踪。
- LTTng是部分基于ftrace的Linux开源跟踪框架,该框架还通过命令行提出了高级用户界面。我们将主机PC端的Trace Compass与日志查看器关联。
参考
- 1. https://elinux.org/Ftrace
- 2. Documentation/trace/ftrace.rst
- 3. http://ex-vi.sourceforge.net/vi.html
- 4. http://ex-vi.sourceforge.net/viin/paper.html
- 有用的外部链接
文件链接 | 文件类型 | 描述 |
---|---|---|
ftrace(kernel.org文档) | 标准 | Linux内核来源的文档 |
使用Ftrace调试内核-第1部分 | 用户指南 | http://lwn.net |
使用Ftrace调试内核-第2部分 | 用户指南 | http://lwn.net |
使用TRACE_EVENT()宏(带有CREATE_TRACE_POINTS) | 训练 | http://lwn.net |
使用ftrace加载性能分析 | 用户指南 | Linaro |