代码之家  ›  专栏  ›  技术社区  ›  Ciro Santilli OurBigBook.com

如何使用ftrace跟踪系统调用事件而不在linux内核中显示任何其他函数?

  •  3
  • Ciro Santilli OurBigBook.com  · 技术社区  · 6 年前

    例如,要监视所有 mkdir 我能想到的最好的办法是:

    #!/bin/sh
    set -eux
    
    d=debug/tracing
    
    mkdir -p debug
    if ! mountpoint -q debug; then
      mount -t debugfs nodev debug
    fi
    
    # Stop tracing.
    echo 0 > "${d}/tracing_on"
    
    # Clear previous traces.
    echo > "${d}/trace"
    
    # Enable tracing mkdir
    echo sys_enter_mkdir > "${d}/set_event"
    
    # Set tracer type.
    echo function > "${d}/current_tracer"
    
    # Filter only sys_mkdir as a workaround.
    echo SyS_mkdir > "${d}/set_ftrace_filter"
    
    # Start tracing.
    echo 1 > "${d}/tracing_on"
    
    # Generate two mkdir calls.
    rm -rf /tmp/a
    rm -rf /tmp/b
    mkdir /tmp/a
    mkdir /tmp/b
    
    # View the trace.
    cat "${d}/trace"
    
    # Stop tracing.
    echo 0 > "${d}/tracing_on"
    
    umount debug
    

    然后在和 sudo 它给出:

    # tracer: function
    #
    # entries-in-buffer/entries-written: 4/4   #P:16
    #
    #                              _-----=> irqs-off
    #                             / _----=> need-resched
    #                            | / _---=> hardirq/softirq
    #                            || / _--=> preempt-depth
    #                            ||| /     delay
    #           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
    #              | |       |   ||||       |         |
               mkdir-31254 [015] .... 2010985.576760: sys_mkdir(pathname: 7ffc54b32c77, mode: 1ff)
               mkdir-31254 [015] .... 2010985.576763: SyS_mkdir <-tracesys_phase2
               mkdir-31255 [007] .... 2010985.578363: sys_mkdir(pathname: 7fff02d90c77, mode: 1ff)
               mkdir-31255 [007] .... 2010985.578365: SyS_mkdir <-tracesys_phase2
    

    我的问题是它为每个系统调用输出两行:

    • sys_mkdir 这就是我想要的
    • SyS_mkdir 这是过滤函数的解决方法,我不想看到

    如果我试着去做:

    echo > "${d}/set_ftrace_filter"
    

    或者根本不要碰那个文件,那么它会显示大量的函数,并且很难找到系统调用。

    如果有更好的方法来禁用常规函数,只保留syscall事件?

    我需要 系统mkdir 我想应该禁用syscall事件,但如果我能使用更具体的事件,感觉会更清楚些?也:

    • 事件显示参数,这更好。
    • syscall函数名在内核版本之间变化。已经是了 __x64_sys_mkdir 而不是 系统mkdir 在Linux v4.18上。

    相关:

    在Ubuntu18.04,Linux内核4.15上测试。

    2 回复  |  直到 6 年前
        1
  •  4
  •   Ciro Santilli OurBigBook.com    6 年前

    使用 nop 示踪剂

    作为 proposed by sruffell ,我们所要做的就是使用 用示踪剂代替 function ,这将禁用函数跟踪,但不会禁用事件。

    与…一起跑 sudo 以下内容:

    #!/bin/sh
    set -eux
    
    d=debug/tracing
    
    mkdir -p debug
    if ! mountpoint -q debug; then
      mount -t debugfs nodev debug
    fi
    
    # Stop tracing.
    echo 0 > "${d}/tracing_on"
    
    # Clear previous traces.
    echo > "${d}/trace"
    
    # Find the tracer name.
    cat "${d}/available_tracers"
    
    # Disable tracing functions, show only system call events.
    echo nop > "${d}/current_tracer"
    
    # Find the event name with.
    grep mkdir "${d}/available_events"
    
    # Enable tracing mkdir.
    # Both statements below seem to do the exact same thing,
    # just with different interfaces.
    # https://www.kernel.org/doc/html/v4.18/trace/events.html
    echo sys_enter_mkdir > "${d}/set_event"
    # echo 1 > "${d}/events/syscalls/sys_enter_mkdir/enable"
    
    # Start tracing.
    echo 1 > "${d}/tracing_on"
    
    # Generate two mkdir calls by two different processes.
    rm -rf /tmp/a /tmp/b
    mkdir /tmp/a
    mkdir /tmp/b
    
    # View the trace.
    cat "${d}/trace"
    
    # Stop tracing.
    echo 0 > "${d}/tracing_on"
    
    umount debug
    

    这将提供所需的输出:

       mkdir-26064 [007] .... 2014370.909743: sys_mkdir(pathname: 7fffbd461c77, mode: 1ff)
       mkdir-26065 [014] .... 2014370.911615: sys_mkdir(pathname: 7ffea53bac77, mode: 1ff)
    

    非最佳解决方案

    这同样有效,但绝对不太好,请替换:

    echo SyS_mkdir > "${d}/set_ftrace_filter"
    

    使用:

    echo '*' > "${d}/set_ftrace_notrace"
    

    这将关闭文档中提到的所有功能: https://www.kernel.org/doc/html/v4.18/trace/ftrace.html#the-file-system

    设置不竞争:

    这与set-ftrace-filter的效果相反。这里添加的任何函数都不会被跟踪。如果在StIfFraceTyFug和StIfFraceTyNoTror中都存在一个函数,函数将 被追踪。

        2
  •  4
  •   red0ct    5 年前

    此外,值得一提的是另一种获得此类信息的简洁方法。人们可以这样做:

    stap -e 'probe syscall.mkdir { printf("%s[%d] -> %s(%s)\n", execname(), pid(), name, argstr) }'
    

    输出 以下内容:

    systemd-journal[318] -> mkdir("/var/log/journal/c8d2562a041649cdbfd1ac5e24dbe0db", 0755)
    systemd-journal[318] -> mkdir("/var/log/journal/c8d2562a041649cdbfd1ac5e24dbe0db", 0755)
    mkdir[4870] -> mkdir("wtf", 0777)
    ...
    

    另一种方式:

    stap -e 'probe kernel.function("sys_mkdir") { printf("%s[%d] (%s)\n", execname(), pid(), $$parms) }'
    

    输出 以下内容:

    systemd-journal[318] (pathname=0x55b74f7ab8b0 mode=0x1ed)
    systemd-journal[318] (pathname=0x55b74f7ab8b0 mode=0x1ed)
    mkdir[8532] (pathname=0x7ffcf30af761 mode=0x1ff)
    ...
    

    您可以根据需要自定义输出。

    P.S.SystemTap基于 kprobes 是的。 Architecture doc 有助于理解它的内部结构。

    More about the SystemTap 是的。

    推荐文章