我正在使用verilog编写一个pci设备并编写其驱动程序, 我可能在硬件设计中插入了一些错误,当我用insmod加载驱动程序时,内核就会卡住并且没有响应。现在我试图弄清楚什么是使我的计算机卡住的最后一个驱动程序代码行。我已经在所有相关的函数中插入了printk,比如probe和init,但是没有打印出来。
当我使用insmod进入我的init函数之前还运行了什么其他代码? (我猜内核会卡在那里)
答案 0 :(得分:1)
printk
通常无法解决此类问题。它们被充分缓冲,如果在调用printk
后系统挂起,您将无法及时看到它们。
选择性地注释掉驱动程序的各个部分并通过消除过程确定哪一行是(第一个)问题会更有效率。
首先评论整个模块的init
部分,只留下return 0;
。构建并加载它。它挂了吗?重新启动系统,重新启用接下来的几行(class_create()
?)并重复。
答案 1 :(得分:1)
根据您的说法,看起来Linux调度程序会被您的驱动程序死锁。这意味着来自系统计时器的中断没有到达或有机会被内核处理。有两个可能的原因:
在所有其他情况下,系统会崩溃,无论是oops还是恐慌都会带有所有适当的输出,或者容忍设备潜在的不当行为。
我想printk
不会在内核模式下挂起这种极端情况。这是非常重的,由于这种不可靠的诊断工具适用于像你这样的场景。
此技巧仅适用于较简单的环境,如引导加载程序或更简单的内核,系统在默认的低端视频模式下运行,并且无需同步访问视频内存。在这样的系统中,通过直接写入视频存储器通过调试输出到显示器的跟踪可能是很好的,并且在很多时候是唯一可用于调试目的的工具。 Linux并非如此。
从软件调试的角度来看,可以推荐哪些技术:
一般情况下,内核调试是一项非常棘手的任务,其中使用了很多技巧,所有这些技巧仅适用于特定的一组案例。 :(
答案 2 :(得分:0)
我会在总线上放置一个逻辑分析仪(在FPGA上你可以使用chipcope或类似的)。然后,您将能够分辨出哪种访问原因(并修复硬件)。无论如何,它将是有用的,以便调试或分析未来的问题。
另一种方法是使用内核崩溃转储实用程序,这在过去让我有些头疼。但是,根据您的Linux发行版需要安装(默认情况下在RH中可用)。见http://people.redhat.com/anderson/crash_whitepaper/
答案 3 :(得分:0)
在你的init之前没有任何东西可以运行。总线枚举是在启动时完成的,如果顺利完成,最早的冻结原因应该是您的驱动程序init AFAIK中的内容。
你应该能够看到printk
被打印出来,它们没有被缓冲,不应该迷路。这仅适用于您可以直接查看内核输出的情况,例如在文本控制台或串行线上。如果还有其他应用程序,比如在X11或ssh中的终端中显示内核日志,它可能没有机会在计算机冻结之前读取和显示日志。
如果由于某些其他原因导致printk
仍然无法正常工作,则可以提前返回初始化函数。只需测试并将返回值移至init中,直到找到崩溃点为止。
很难说是什么导致你的冻结,但中断是我首先要看的东西之一。确保设备确实不会发出中断信号,直到驱动程序启用它们(包括清除中断使能系统复位),并且只有在所有处理程序都被注册后才能在驱动程序中启用它们(同样,在启用中断之前清除中断状态)。
要看的第二件事是总线主传输,同样的事情适用:确保设备没有做任何事情,直到它被要求并让驱动程序确保没有总线传输之前有效在设备级别启用busmastering。
答案 4 :(得分:0)
安装驱动程序模块后内核卡住的事实让我想知道是否有其他驱动程序(内置于内核?)已经在驱动设备。我犯了这个错误,这就是我要问的原因。我正在寻找正在使用的字符串"内核驱动程序"在< lspci'的输出中在安装模块之前。无论如何,你的printk应该在dmesg输出中可见。
答案 5 :(得分:0)
除了克劳迪奥的建议外,还有更多的调试思路: 1.尝试kgdb(https://www.kernel.org/doc/htmldocs/kgdb/EnableKGDB.html) 2.使用JTAG接口连接到调试工具(我认为这些设备因供应商而异,因此您必须弄清楚特定硬件需要哪些调试工具)