linux kernel debug 之 CallTrace

本文针对UWB无线调试中出现的Kernel警告问题进行了深入分析,并提供了具体的解决方案,包括Kernel中断请求与释放、内存页分配与释放及内核锁等方面的内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇文章是基于上次UWB(WUSB) wireless debug 的一个问题,然后引申出来的一个话题,对kenel有一定理解的同学可能会有一定的帮助。

--其实这个问题,个人认为,这个个CallTrace会一起down机,cpuhold的等问题,还是一个很大的问题。不过从一般意义上来讲,他是个warning我们可以不用管他。但谁让自己是做技术的呢,没办法,眼里容不得沙子。来吧干货。

1.      Kernel int request & free

Call Trace:

Apr  7 10:44:56 magic kernel: ------------[ cuthere ]------------

Apr  7 10:44:56 magic kernel: WARNING: atkernel/softirq.c:159 local_bh_enable_ip+0x7d/0xb0() (Tainted: P           ---------------   )

Apr  7 10:44:56 magic kernel: Hardware name: HPZ420 Workstation

Apr  7 10:44:56 magic kernel: Modules linked in:usb_skeleton(U) wusb_cbaf(U) elok_s(P)(U) tun bridge iptable_mangle iptable_natnf_nat nf_conntrack_ipv4 nf_conntrack nf_defrag_ipv4 iptable_filter ip_tablessunrpc bnx2fc cnic uio fcoe libfcoe 8021q garp stp libfc llc scsi_transport_fcscsi_tgt cpufreq_ondemand acpi_cpufreq freq_table mperf ipv6 rcim2usb(U)psysdrv(P)(U) esdcan_pci200(P)(U) realtek_uwb(U) vfat fat hwa_hc(U) wusb_wa(U)ext3 wusbcore(U) jbd hwa_rc(U) uwb(U) wmi xhci_hcd nvidia(P)(U) igb dca ptppps_core sg microcode serio_raw i2c_i801 i2c_core iTCO_wdt iTCO_vendor_supportsnd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_intel snd_hda_codec snd_hwdepsnd_seq snd_seq_device snd_pcm snd_timer snd soundcore snd_page_alloc e1000eshpchp ext4 mbcache jbd2 sd_mod crc_t10dif sr_mod cdrom firewire_ohcifirewire_core crc_itu_t isci libsas mpt2sas scsi_transport_sas raid_class ahcipata_acpi ata_generic dm_mirror dm_region_hash dm_log dm_mod [last unloaded:scsi_wait_scan]

Apr  7 10:44:56 magic kernel: Pid: 6127, comm:java Tainted: P          ---------------   2.6.32-358.11.1.el6.x86_64 #1

Apr  7 10:44:56 magic kernel: Call Trace:

Apr  7 10:44:56 magic kernel: <IRQ>  [<ffffffff8106e2e7>] ? warn_slowpath_common+0x87/0xc0

Apr  7 10:44:56 magic kernel:[<ffffffff8106e33a>] ? warn_slowpath_null+0x1a/0x20

Apr  7 10:44:56 magic kernel:[<ffffffff810778dd>] ? local_bh_enable_ip+0x7d/0xb0

Apr  7 10:44:56 magic kernel:[<ffffffff815106db>] ? _spin_unlock_bh+0x1b/0x20

Apr  7 10:44:56 magic kernel:[<ffffffffa0bcd8f7>] ? uwb_rc_set_drp_cmd_done+0x67/0x100 [uwb]

Apr  7 10:44:56 magic kernel:[<ffffffff8108107d>] ? del_timer+0x7d/0xe0

Apr  7 10:44:56 magic kernel:[<ffffffffa0bd0e95>] ? uwb_rc_neh_cb+0x25/0x40 [uwb]

Apr  7 10:44:56 magic kernel:[<ffffffffa0bd11a2>] ? uwb_rc_neh_grok+0x252/0x4d0 [uwb]

Apr  7 10:44:56 magic kernel:[<ffffffffa01e6e39>] ? hwarc_neep_cb+0x59/0x168 [hwa_rc]

Apr  7 10:44:56 magic kernel:[<ffffffff813b4ad4>] ? usb_hcd_giveback_urb+0x64/0xe0

Apr  7 10:44:56 magic kernel:[<ffffffffa0c6a26e>] ? xhci_irq+0x4be/0x17f0 [xhci_hcd]

Apr  7 10:44:56 magic kernel:[<ffffffff81082128>] ? add_timer+0x18/0x30

Apr  7 10:44:56 magic kernel:[<ffffffff810e70ea>] ? __rcu_process_callbacks+0x25a/0x350

Apr  7 10:44:56 magic kernel:[<ffffffffa0c6b5d1>] ? xhci_msi_irq+0x31/0x40 [xhci_hcd]

Apr  7 10:44:56 magic kernel:[<ffffffff810e1670>] ? handle_IRQ_event+0x60/0x170

Apr  7 10:44:56 magic kernel:[<ffffffff8107700f>] ? __do_softirq+0x11f/0x1e0

Apr  7 10:44:56 magic kernel:[<ffffffff810e3dbe>] ? handle_edge_irq+0xde/0x180

Apr  7 10:44:56 magic kernel:[<ffffffff8100de89>] ? handle_irq+0x49/0xa0

Apr  7 10:44:56 magic kernel:[<ffffffff815171bc>] ? do_IRQ+0x6c/0xf0

Apr  7 10:44:56 magic kernel: [<ffffffff8100b9d3>]? ret_from_intr+0x0/0x11

Apr  7 10:44:56 magic kernel: <EOI>

Apr  7 10:44:56 magic kernel: ---[ end trace580801de7dc9f3db ]---

Apr  7 10:44:56 magic kernel: in uwb_rsv_timer

结合Call Trace,我们上相应内核代码:

static inline void _local_bh_enable_ip(unsignedlong ip)

{

         WARN_ON_ONCE(in_irq()|| irqs_disabled());

#ifdef CONFIG_TRACE_IRQFLAGS

         local_irq_disable();

#endif

         /*

          * Are softirqs going to be turned on now:

          */

         if(softirq_count() == SOFTIRQ_DISABLE_OFFSET)

                   trace_softirqs_on(ip);

         /*

          * Keep preemption disabled until we are donewith

          * softirq processing:

         */

         sub_preempt_count(SOFTIRQ_DISABLE_OFFSET- 1);

 

         if(unlikely(!in_interrupt() && local_softirq_pending()))

                   do_softirq();

 

         dec_preempt_count();

#ifdef CONFIG_TRACE_IRQFLAGS

         local_irq_enable();

#endif

         preempt_check_resched();

}

 

warning是由WARN_ON_ONCE(in_irq()|| irqs_disabled());代码产生的

 

解决方法

解决了disconnect CallTrace

/drivers/usb/host/hwa-hc.c

static void hwahc_disconnect(structusb_interface *usb_iface)

{

       struct usb_hcd *usb_hcd;

       struct wusbhc *wusbhc;

       struct hwahc *hwahc;

 

       printk("in hwahc_disconnect\n");

 

       usb_hcd = usb_get_intfdata(usb_iface);

       wusbhc = usb_hcd_to_wusbhc(usb_hcd);

       hwahc = container_of(wusbhc, struct hwahc, wusbhc);

 

 

       wusbhc_b_destroy(&hwahc->wusbhc);

       usb_remove_hcd(usb_hcd);

       hwahc_destroy(hwahc);

       usb_put_hcd(usb_hcd);

}

 

static int hwahc_probe(struct usb_interface*usb_iface,

                       const structusb_device_id *id)

{

                   …

                   usb_hcd->wireless= 1;

       usb_hcd->irq= -1;

                  

}

 

以上解决了disconnect的问题。

2.      Memory page alloc & free

Call Trace

Jun 11 03:09:14magic kernel: [  263.849177]  [<ffffffff81137d09>] ?free_pages+0x49/0x50

Jun 11 03:09:14magic kernel: [  263.849186]  [<ffffffffa01949b2>] ? hwarc_neep_release+0x32/0x40[hwa_rc]

Jun 11 03:09:14magic kernel: [  263.849202]  [<ffffffffa0359f7b>] ? uwb_rc_rm+0x3b/0xd0 [uwb]

Jun 11 03:09:14magic kernel: [  263.849211]  [<ffffffffa01940a1>] ?hwarc_disconnect+0x41/0x70 [hwa_rc]

Jun 11 03:09:14magic kernel: [  263.849225]  [<ffffffff813d5998>] ?usb_unbind_interface+0x78/0x160

Jun 11 03:09:14magic kernel: [  263.849235]  [<ffffffff8137407f>] ?__device_release_driver+0x6f/0xe0

Jun 11 03:09:14magic kernel: [  263.849241]  [<ffffffff813741ed>] ?device_release_driver+0x2d/0x40

Jun 11 03:09:14magic kernel: [  263.849248]  [<ffffffff813730f3>] ?bus_remove_device+0xa3/0x110

Jun 11 03:09:14magic kernel: [  263.849258]  [<ffffffff81370b2d>] ?device_del+0x12d/0x1e0

Jun 11 03:09:14magic kernel: [  263.849266]  [<ffffffff813d1c50>] ?usb_disable_device+0xb0/0x2b0

Jun 11 03:09:14magic kernel: [  263.849273]  [<ffffffff813ca862>] ?usb_disconnect+0xa2/0x1c0

Jun 11 03:09:14magic kernel: [  263.849280]  [<ffffffff813cc6fe>] ?hub_thread+0x75e/0x1820

Jun 11 03:09:14magic kernel: [  263.849291]  [<ffffffff8100969d>] ?__switch_to+0x7d/0x340

Jun 11 03:09:14magic kernel: [  263.849304]  [<ffffffff810a1460>] ?autoremove_wake_function+0x0/0x40

Jun 11 03:09:14magic kernel: [  263.849311]  [<ffffffff813cbfa0>] ?hub_thread+0x0/0x1820

Jun 11 03:09:14magic kernel: [  263.849320]  [<ffffffff810a0fce>] ?kthread+0x9e/0xc0

Jun 11 03:09:14magic kernel: [  263.849327]  [<ffffffff8100c28a>] ?child_rip+0xa/0x20

Jun 11 03:09:14 magickernel: [  263.849336]  [<ffffffff810a0f30>] ? kthread+0x0/0xc0

Jun 11 03:09:14magic kernel: [  263.849341]  [<ffffffff8100c280>] ?child_rip+0x0/0x20

Jun 11 03:09:14magic kernel: [  263.849345] Disablinglock debugging due to kernel taint

 

/drivers/uwb /hwa-rc.c

staticvoid hwarc_neep_release(struct uwb_rc *rc)

{

        struct hwarc *hwarc = rc->priv;

 

        usb_kill_urb(hwarc->neep_urb);

        usb_free_urb(hwarc->neep_urb);

        printk("%srd_buffer=%p\n",__func__, hwarc->rd_buffer);

        if (hwarc->rd_buffer != NULL){

                printk("%srd_buffer=%p\n",__func__, hwarc->rd_buffer);

                free_page((unsigned long)hwarc->rd_buffer);

                hwarc->rd_buffer = NULL;

        }

}

 

 

staticint hwarc_post_reset(struct usb_interface *iface)

{

        struct hwarc *hwarc = NULL;

        ssleep(1);

        hwarc = usb_get_intfdata(iface);

        if(hwarc == NULL){

                printk("hwarc_post_reset:ERROR hwarc is NULL in hwarc_post_reset\n");

                return 0;

        }

        struct uwb_rc *uwb_rc =hwarc->uwb_rc;

 

        return uwb_rc_post_reset(uwb_rc);

}

以上解决了内核Page free的问题。

 

3.      Kernellock

Call Trace

About the Spin lock. Kernel lock:mutex_lock  semaphore_lock  spin_lock atomic_lock

/drivers/uwb/drp.c  +913

static voiduwb_rc_set_drp_cmd_done(struct uwb_rc *rc, void *arg,

                                    structuwb_rceb *reply, ssize_t reply_size)

{

        struct uwb_rc_evt_set_drp_ie *r =(struct uwb_rc_evt_set_drp_ie *)reply;

        unsigned long flags;

        printk("inuwb_rc_set_drp_cmd_done!!!!!!!!\n");

 

        if (r != NULL) {

                if (r->bResultCode !=UWB_RC_RES_SUCCESS)

                       dev_err(&rc->uwb_dev.dev, "SET-DRP-IE failed: %s(%d)\n",

                                uwb_rc_strerror(r->bResultCode),r->bResultCode);

        } else

               dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: timeout\n");

 

        //spin_lock_bh(&rc->rsvs_lock);

       spin_lock_irqsave(&rc->rsvs_lock, flags);

        if (rc->set_drp_ie_pending > 1) {

                rc->set_drp_ie_pending = 0;

                uwb_rsv_queue_update(rc);

        } else {

                rc->set_drp_ie_pending = 0;

        }

        spin_unlock_irqrestore(&rc->rsvs_lock, flags);

        //spin_unlock_bh(&rc->rsvs_lock);

}

 

以上解决了内核锁嵌套问题!

<think>好的,用户现在问的是如何打印GFP_KERNEL的配置。首先,我需要回忆一下GFP_KERNEL是什么。GFP_KERNELLinux内核中内存分配时使用的标志,表示在正常进程上下文中进行内存分配,可能会触发直接回收或IO操作,导致睡眠。用户的问题可能是想在内核开发或调试时,查看哪些地方使用了GFP_KERNEL标志,或者想配置内核以记录相关的内存分配信息。 首先,我需要确定用户的使用场景。用户可能在进行内核模块开发,遇到了内存分配的问题,或者需要调试内存使用情况,想知道如何跟踪GFP_KERNEL的使用。可能的用户身份是内核开发者或系统程序员,对内核有一定的了解,但需要具体的配置方法。 接下来,用户的需求可能不仅仅是打印GFP_KERNEL的配置,而是希望在内核日志中捕获使用该标志的内存分配事件。因此,我需要考虑如何在内核中启用相关调试选项,或者使用动态调试工具来跟踪GFP_KERNEL的使用。 之前的对话中,用户询问了默认的控制台日志级别,现在转向具体的内核内存分配标志,可能是在调试过程中遇到了更深入的问题。用户可能需要了解如何配置内核或使用工具来记录GFP_KERNEL的分配情况,以便分析内存使用或排查问题。 我需要检查内核中的配置选项,例如CONFIG_DEBUG_KMEMLEAK,或者动态调试功能如ftracetracepoints。另外,可能需要使用dmesg或systemtap等工具来捕获相关信息。此外,用户可能需要了解如何修改内核启动参数或使用sysctl来调整日志级别,确保相关调试信息被记录。 需要注意的是,GFP_KERNEL本身是一个内存分配标志,而不是一个可配置的参数,所以用户的问题可能更偏向于如何在内核中跟踪或记录使用该标志的分配操作。这可能涉及到内核的调试选项、动态追踪工具或日志配置。需要详细说明这些方法,并给出具体的步骤和示例命令,帮助用户实现目标。 另外,用户可能需要区分不同的内核版本,因为不同版本的内核调试工具和配置方式可能有所不同。因此,在回答时应提及这些可能的差异,并建议用户参考对应内核版本的文档。同时,提醒用户开启调试功能可能会影响系统性能,需谨慎使用。 最后,总结可能的配置方法,包括编译时选项、动态调试、日志过滤等,确保用户能够根据自身情况选择合适的方式,并正确实施。</think>以下是关于打印`GFP_KERNEL`内存分配信息的配置方法及原理的逐步说明: --- ### 1. **理解`GFP_KERNEL`** - **基本定义** `GFP_KERNEL`是Linux内核中用于**常规内存分配**的标志(`Get Free Pages`标志),表示: - 在进程上下文(可睡眠)中分配内存 - 可能触发直接内存回收或I/O操作 - **应用场景** 主要用于内核模块、驱动程序中非原子上下文的动态内存分配,例如: ```c void *ptr = kmalloc(size, GFP_KERNEL); ``` --- ### 2. **打印`GFP_KERNEL`分配信息的需求** 若需要跟踪`GFP_KERNEL`内存分配行为(如调试内存泄漏或性能问题),需通过以下方式实现: --- ### 3. **内核编译时配置** #### 方法1:启用`SLUB/SLAB`调试支持 1. **配置内核选项** 在内核配置文件中启用: ```bash CONFIG_SLUB_DEBUG=y # 启用SLUB分配器调试 CONFIG_DEBUG_KMEMLEAK=y # 内核内存泄漏检测 ``` > 通过`make menuconfig`路径: > `Kernel Hacking` → `Memory Debugging` 2. **启动参数设置** 在GRUB启动参数中添加: ```bash slub_debug=FZP # 启用完整SLUB调试 kmemleak=on # 开启内存泄漏检测 ``` 3. **查看分配信息** - 通过`dmesg`观察分配调用栈: ```bash dmesg | grep "GFP_KERNEL" ``` --- #### 方法2:使用动态调试(Dynamic Debug) 1. **启用动态追踪** 在内核配置中开启: ```bash CONFIG_DYNAMIC_DEBUG=y ``` 2. **激活`GFP_KERNEL`相关日志** 通过`debugfs`动态控制: ```bash echo 'file mm/page_alloc.c +p' > /sys/kernel/debug/dynamic_debug/control ``` > 此命令会打印所有`page_alloc.c`中的内存分配操作 --- ### 4. **运行时追踪工具** #### 方法1:通过`ftrace`跟踪 ```bash # 启用函数追踪 echo function > /sys/kernel/tracing/current_tracer # 过滤`GFP_KERNEL`相关分配函数 echo '__kmalloc*' > /sys/kernel/tracing/set_ftrace_filter # 开始记录 echo 1 > /sys/kernel/tracing/tracing_on # 查看结果 cat /sys/kernel/tracing/trace ``` #### 方法2:使用`systemtap`脚本 编写脚本`gfp_trace.stp`: ```stap probe kernel.function("__kmalloc") { if ($flags & __GFP_KERNEL) printf("GFP_KERNEL call: %s\n", ppfunc()) } ``` --- ### 5. **日志级别过滤** 若需在控制台直接打印`GFP_KERNEL`分配信息,需调整内核日志级别: ```bash # 临时降低控制台日志级别(允许打印调试信息) echo 8 > /proc/sys/kernel/printk # 或通过启动参数永久设置 GRUB_CMDLINE_LINUX="loglevel=7" ``` --- ### 6. **示例输出解析 典型的内核日志条目可能包含: ``` [ 123.456789] kmalloc(size=4096, flags=GFP_KERNEL) from [<abcd1234>] my_module_init+0x20/0x100 ``` - `size`:分配的内存大小 - `flags`:使用的分配标志 - `my_module_init+0x20`:调用函数地址及偏移量 --- ### 7. **注意事项 | 配置方式 | 优点 | 缺点 | |-------------------|-----------------------|---------------------------| | 内核编译调试 | 信息完整 | 需要重新编译内核 | | 动态调试 | 实时控制 | 可能产生大量日志 | | ftrace/systemtap | 灵活低开销 | 需要学习脚本语法 | - **性能影响**:开启调试后可能显著降低系统性能 - **日志管理**:建议通过`logrotate`或`journald`管理日志文件大小 --- ### 8. **验证配置 通过观察`/var/log/kern.log`或直接运行: ```bash dmesg -wH | grep -E "GFP_KERNEL|kmalloc" ``` 若配置成功,将看到包含`GFP_KERNEL`标志的内存分配记录。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值