Linux kernel 使用us定时器逐个函数(仅限最大值)跟踪linux内核

Linux kernel 使用us定时器逐个函数(仅限最大值)跟踪linux内核,linux-kernel,trace,Linux Kernel,Trace,我想知道linux内核如何做一些事情(接收tcp数据包)。按什么顺序调用主tcp函数。我想看到中断处理程序(上半部分)、下半部分,甚至在用户调用“read()”后内核完成的工作 如何从内核中获得具有线性时间标度的函数跟踪 我希望从单个数据包中获得跟踪,而不是在接收第1000个数据包时内核的配置文件 内核是2.6.18或2.6.23(我的debian支持)。我可以给它添加一些补丁。我无法立即找到一种一次只跟踪一个数据包的方法。特别是,由于中断处理程序的上半部分不应该执行任何阻塞操作(这很容易死锁)

我想知道linux内核如何做一些事情(接收tcp数据包)。按什么顺序调用主tcp函数。我想看到中断处理程序(上半部分)、下半部分,甚至在用户调用
“read()”
后内核完成的工作

如何从内核中获得具有线性时间标度的函数跟踪

我希望从单个数据包中获得跟踪,而不是在接收第1000个数据包时内核的配置文件


内核是2.6.18或2.6.23(我的debian支持)。我可以给它添加一些补丁。

我无法立即找到一种一次只跟踪一个数据包的方法。特别是,由于中断处理程序的上半部分不应该执行任何阻塞操作(这很容易死锁),因此很难获得这种细粒度的跟踪

也许这太迂腐了,但是你看过源代码了吗?根据经验,我知道TCP层在记录意图和引用RFC方面都有很好的注释


我强烈推荐TCP/IP插图,esp第2卷,实现()。它非常好,一行一行地浏览代码。根据描述,“结合500个插图和15000行真实的工作代码…”。所包含的源代码来自BSD内核,但栈极为相似,比较两者通常很有指导意义。

您需要。它可以为您的整个系统(选定的子集)提供计时,这意味着您可以通过内核和所有库,从设备到应用程序再到应用程序跟踪网络活动。

我认为最接近的工具是kernelftrace,它至少可以部分实现您想要的功能。下面是一个示例用法:

root@ansis-xeon:/sys/kernel/debug/tracing# cat available_tracers 
blk function_graph mmiotrace function sched_switch nop
root@ansis-xeon:/sys/kernel/debug/tracing# echo 1 > ./tracing_on 
root@ansis-xeon:/sys/kernel/debug/tracing# echo function_graph > ./current_trace
root@ansis-xeon:/sys/kernel/debug/tracing# cat trace

 3)   0.379 us    |        __dequeue_entity();
 3)   1.552 us    |      }
 3)   0.300 us    |      hrtick_start_fair();
 3)   2.803 us    |    }
 3)   0.304 us    |    perf_event_task_sched_out();
 3)   0.287 us    |    __phys_addr();
 3)   0.382 us    |    native_load_sp0();
 3)   0.290 us    |    native_load_tls();
 ------------------------------------------
 3)    <idle>-0    =>  ubuntuo-2079 
 ------------------------------------------

 3)   0.509 us    |              __math_state_restore();
 3)               |              finish_task_switch() {
 3)   0.337 us    |                perf_event_task_sched_in();
 3)   0.971 us    |              }
 3) ! 100015.0 us |            }
 3)               |            hrtimer_cancel() {
 3)               |              hrtimer_try_to_cancel() {
 3)               |                lock_hrtimer_base() {
 3)   0.327 us    |                  _spin_lock_irqsave();
 3)   0.897 us    |                }
 3)   0.305 us    |                _spin_unlock_irqrestore();
 3)   2.185 us    |              }
 3)   2.749 us    |            }
 3) ! 100022.5 us |          }
 3) ! 100023.2 us |        }
 3)   0.704 us    |        fget_light();
 3)   0.522 us    |        pipe_poll();
 3)   0.342 us    |        fput();
 3)   0.476 us    |        fget_light();
 3)   0.467 us    |        pipe_poll();
 3)   0.292 us    |        fput();
 3)   0.394 us    |        fget_light();
 3)               |        inotify_poll() {
 3)               |          mutex_lock() {
 3)   0.285 us    |            _cond_resched();
 3)   1.134 us    |          }
 3)   0.289 us    |          fsnotify_notify_queue_is_empty();
 3)               |          mutex_unlock() {
 3)   2.987 us    |        }
 3)   0.292 us    |        fput();
 3)   0.517 us    |        fget_light();
 3)   0.415 us    |        pipe_poll();
 3)   0.292 us    |        fput();
 3)   0.504 us    |        fget_light();
 3)               |        sock_poll() {
 3)   0.480 us    |          unix_poll();
 3)   4.224 us    |        }
 3)   0.183 us    |        fput();
 3)   0.341 us    |        fget_light();
 3)               |        sock_poll() {
 3)   0.274 us    |          unix_poll();
 3)   0.731 us    |        }
 3)   0.182 us    |        fput();
 3)   0.269 us    |        fget_light();
root@ansis-xeon:/sys/kernel/debug/tracing#cat可用#跟踪器
blk功能图M接口功能表开关nop
root@ansis-xeon:/sys/kernel/debug/tracing#echo 1>/tracing_on
root@ansis-xeon:/sys/kernel/debug/tracing#echo function_graph>/current_trace
root@ansis-xeon:/sys/kernel/debug/tracing#cat trace
3) 0.379 us | u_u出列实体();
3) 1.552美国|}
3) 0.300美元| hrtick_start_fair();
3) 2.803美国|}
3) 0.304美国|性能事件|任务|计划|;
3) 0.287美国物理地址();
3) 0.382 us |本机负载(sp0);
3) 0.290 us |本地负载(tls);
------------------------------------------
3) -0=>ubuntuo-2079
------------------------------------------
3) 0.509 us | uu数学u状态u还原();
3) |完成_任务_开关(){
3) 0.337 us | perf|u event_task_sched_in();
3) 0.971 us |}
3) ! 100015.0美元|}
3) | hrtimer_cancel(){
3) | hrtimer_尝试_取消(){
3) |锁定计时器(基础){
3) 0.327 us | | | | U自旋(U锁定)irqsave();
3) 0.897 us |}
3) 0.305 us | |(旋转)(解锁)(irqrestore);
3) 2.185美国|}
3) 2.749美国|}
3) ! 100022.5美国|}
3) ! 100023.2美国|}
3) 0.704 us | fget_light();
3) 0.522美制管道;
3) 0.342 us | fput();
3) 0.476 us | fget_light();
3) 0.467美制管道;
3) 0.292 us | fput();
3) 0.394 us | fget_light();
3) | inotify_poll(){
3) |互斥锁(){
3) 0.285 us | | u cond_resched();
3) 1.134美国|}
3) 0.289 us | fsnotify_notify_queue_为空();
3) |互斥解锁(){
3) 2.987美国|}
3) 0.292 us | fput();
3) 0.517 us | fget|u light();
3) 0.415美国|管道|投票();
3) 0.292 us | fput();
3) 0.504 us | fget_light();
3) | sock_poll(){
3) 0.480 us | unix|u poll();
3) 4.224美国|}
3) 0.183美元| fput();
3) 0.341 us | fget|u light();
3) | sock_poll(){
3) 0.274 us | unix|u poll();
3) 0.731美|}
3) 0.182 us | fput();
3) 0.269 us | fget|u light();
它并不完美,因为它不打印函数参数,并且遗漏了一些静态函数,但是您可以知道谁在内核中调用谁

如果这还不够,那么就使用GDB。但是您可能已经知道,为内核调试设置GDB并不像为用户空间进程设置GDB那么容易。如果需要的话,我更喜欢使用GDB+qemu

快乐追踪


更新:在以后的Linux发行版上,我建议使用
trace cmd
命令行工具,即“包装器”关于
/sys/kernel/debug/tracing
trace cmd
的使用比原始的内核界面提供的直观得多。

这个问题很老,可能与最初的海报不相关,但我最近使用的一个很好的技巧对我很有帮助,就是将sk_buf的“mark”字段设置为某个值,并且只设置为“printk”如果值匹配

因此,例如,如果您知道上半部分IRQ处理程序(如问题所示)的位置,那么您可以硬编码一些检查(例如tcp端口、源IP、源MAC地址,以及您得到的点),并将标记设置为任意值(例如skb->mark=0x9999)

如果标记具有相同的值,则一直向上您只打印k。只要没有其他人更改您的标记(据我所知,这通常是典型设置中的情况),那么您将只看到您感兴趣的数据包


因为大多数有趣的函数都有skb,所以它几乎适用于所有有趣的函数。

TCP/IP插图已经在我的pc上的adobe中打开:)。它是关于BSD.T的