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