我有两个相同的raspberry pi 3 b +设备,一个运行在raspberrypi-kernel_1.20180313-1上,另一个运行在raspberrypi-kernel_1.20180417-1上。我正在两个设备上都使用“ hcidump -R”观看蓝牙事件。一台设备显示蓝牙事件,另一台不显示。我已经在设备上交换了SD卡,以确认它与硬件无关,无论SD卡位于哪个设备上,运行20180313的设备都会显示蓝牙事件,而20180417则不会。
为调试此问题,我一直在从git提取的raspbian源代码的各个点添加一些printk语句: https://github.com/raspberrypi/linux
我觉得最开始进行调试的地方是蓝牙RX代码,例如为发送到线路规程的每个蓝牙消息打印内容。具体来说,在drivers / bluetooth / hci_ldisc.c中的hci_uart_tty_receive函数中,我在开头添加了两行:
printk(KERN_ERR "AARON: In hci_uart_tty_receive with tty %p\n", tty);
dump_stack();
重建内核并启动设备后,在运行20180313的pi上,我看不到日志消息/堆栈跟踪,而在其他pi上,我什么都没看到,表明未到达蓝牙RX代码。因此,为了进一步调试,我查看了堆栈跟踪,即:
Jul 9 21:03:18 tiltpi kernel: [ 9.391137] Workqueue: events_unbound flush_to_ldisc
Jul 9 21:03:18 tiltpi kernel: [ 9.391166] [<8010f664>] (unwind_backtrace) from [<8010bd1c>] (show_stack+0x20/0x24)
Jul 9 21:03:18 tiltpi kernel: [ 9.391183] [<8010bd1c>] (show_stack) from [<80449c20>] (dump_stack+0xc8/0x114)
Jul 9 21:03:18 tiltpi kernel: [ 9.391221] [<80449c20>] (dump_stack) from [<7f4400cc>] (hci_uart_tty_receive+0x5c/0xac [hci_uart])
Jul 9 21:03:18 tiltpi kernel: [ 9.391254] [<7f4400cc>] (hci_uart_tty_receive [hci_uart]) from [<804b9bdc>] (tty_ldisc_receive_buf+0x64/0x6c)
Jul 9 21:03:18 tiltpi kernel: [ 9.391273] [<804b9bdc>] (tty_ldisc_receive_buf) from [<804ba15c>] (flush_to_ldisc+0xcc/0xe4)
Jul 9 21:03:18 tiltpi kernel: [ 9.391293] [<804ba15c>] (flush_to_ldisc) from [<80135934>] (process_one_work+0x144/0x438)
Jul 9 21:03:18 tiltpi kernel: [ 9.391311] [<80135934>] (process_one_work) from [<80135c68>] (worker_thread+0x40/0x574)
Jul 9 21:03:18 tiltpi kernel: [ 9.391328] [<80135c68>] (worker_thread) from [<8013b930>] (kthread+0x108/0x124)
Jul 9 21:03:18 tiltpi kernel: [ 9.391352] [<8013b930>] (kthread) from [<80107ed4>] (ret_from_fork+0x14/0x20)
我继续为flush_to_ldisc和tty_ldisc_receive_buf添加printk语句,重新编译并重新测试。但是,尽管我继续看到在hci_uart_tty_receive中添加的printk消息,但没有看到添加到flush_to_ldisc或tty_ldisc_receive_buf中的消息。
在进一步检查内核源代码时,我发现堆栈跟踪甚至都没有意义,因为列出的功能没有直接相互调用。更具体地说,在tty_buffer.c中,flush_to_ldisc(朝向堆栈的底部)调用receive_buf,然后调用tty_ldisc_receive_buf,后者随后将调用hci_ldisc.c中的hci_uart_tty_receive。内核堆栈没有receive_buf的任何条目,并显示flush_to_ldisc直接调用_tty_ldisc_receive_buf。
所以我很困惑。我在内核源代码中进行了搜索,未发现“ flush_to_ldisc”或“ tty_ldisc_receive_buf”函数的其他声明。
为什么/如何dump_stack()缺少堆栈条目?为什么我放在堆栈底部的函数中的prink语句没有显示,而我放在堆栈顶部的printk语句却没有显示呢?
编辑:
更多搜索显示Linux内核依赖gcc进行某些优化,包括某些函数的自动内联,因此这很可能发生在我的堆栈跟踪中。那可以解释为什么我看不到堆栈中明确列出的函数,但是也不能解释为什么printk输出没有显示出来。任何人都对为什么printk语句会从栈顶而不是栈底出现的想法有何想法?使用以下命令设置rsyslog.conf文件:
*.err -/var/log/errors.log
我添加的所有printk语句都类似于“ printk(KERN_ERR“ string \ n”);“
EDIT2:更新了问题标题,以反映出它不仅仅是关于printk输出的缺失。
EDIT3:我删除了内核源代码的本地副本,再次将其拉出,添加了我的printk语句,并从头开始重新编译,现在我得到了printk语句。我添加的代码似乎没有重新编译或链接到内核版本中。我在制作内核之前先执行了“ make clean”操作,但似乎仍未正确编译/链接某些内容。但是开始清理可以解决问题。
摘要:Linux内核利用了gcc优化,即使没有在源中显式指定为内联,这些内联也会导致函数被内联编译。而且,当您“确定”已使用所做的更改重新编译了内核时,应从干净的源代码/构建目录重新开始,并尝试第二次,然后再将问题堆积。