• Linux驱动设计—— 驱动调试技术


    参考博客与书籍:

    《Linux设备驱动开发详解》

    《Linux设备驱动程序》

    http://blog.chinaunix.net/uid-24219701-id-2884942.html

    对于驱动程序设计来说,核心问题之一就是如何完成调试。当前常用的驱动调试技术可分为:

    1. 打印调试

      printk

      重定向控制台消息

      消息记录

      开启和关闭消息速度限制

      打印设备编号

    2. 调试器调试

      gdb

      kdb内核调试器

      kgdb补丁  

    3. 查询调试

      使用/proc文件系统

      ioctl方法

    4. 监视调试

      oops消息

    5. 工具包

      动态探测(DProbes,一种调试工具) 

      Linux跟踪工具包


    打印调试 (类似编写应用程序时常用条件编译的Debug宏)

    细节参考http://blog.csdn.net/flowingflying/article/details/4534120

    在驱动开发时,printk 非常有助于调试。但当正式发行驱动程序时应当去掉这些打印语句。但你有可能很快又发现,你又需要在驱动程序中实现一个新功能(或者修复一个bug),这时你又要用到那些被删除的打印语句。这里介绍一种使用printk 的合理方法,可以全局地打开或关闭它们,而不是简单地删除

    #ifdef PDEBUG
    #define PLOG(fmt,args...) printk(KERN_DEBUG"scull:"fmt,##args)
    #else
    #define PLOG(fmt,args...) /*do nothing */
    #endif

    Makefile作如下修改:

    DEBUG =y
    ifeq ($(DEBUG),y)
    DEBFLAGS =-O2 -g -DPDEBUG
    else
    DEBFLAGS =-O2
    endif
    CFLAGS +=$(DEBFLAGS)
    

    实例:

    /*
     * 输出调试信息
     * Lzy     2011-9-26
     */
    #include <linux/init.h>             
    #include <linux/module.h>      
    #define DEBUG_SWITCH 1   /*1:输出 0:不输出*/
    
    #if DEBUG_SWITCH
    #define P_DEBUG(fmt,args...) printk("<kernel>:[%s]<Function> [%d]Line: "fmt, __FUNCTION__, __LINE__, ##args)
    #else
    #define P_DEBUG(fmt,args...) /*do nothing */
    #endif
    
    static int hello_init(void)
    {   
        char *name = "Lzy";
        P_DEBUG( "Hello %s
    ",name);    /* 打印hello World */
        return 0;
    }
    
    static void hello_exit(void)
    {
        P_DEBUG( "Goodbye, world
    ");   /* 打印Goodbye,world */
    }
    
    module_init(hello_init);   /* 指定模块加载函数 */
    module_exit(hello_exit);   /* 指定模块卸载函数 */
    
    MODULE_LICENSE("GPL");
    

    调试工具: GDB ,KDB,KGDB

    都需要编译DEBUG版本内核。

    KDB单机汇编级调试,需要单独下载kernel对应的patch,

    GDB没整明白,只知道 gdb vmlinux启动后 通过add-symobl-file增加被调试模块的符号信息

    KGDB 在2.6.*后就已缺省放在内核源码里了,其他的需要单独下载PATCH,反正我的2.6.18内核里没有(在kernel.org中,people/ark 下应该能找到2.6.18的patch,注意打patch的顺序)

       查看是否有KGDB的方法是:源码路径下make menuconfig后能看到KGDB这一项。下面主要介绍2.6.18上KGDB环境的建立:

          KGDB需要两台机器配合,一个开发机,一个测试机,两台机器通过串口线连接(该线是需要处理的,具体的与window上调试驱地的一致)

          a.硬件连接性测试:在开发机上 执行 stty -ispeed 115200 -ospeed 115200 -F /dev/ttyS0

                                      在测试机上 执行 stty -ispeed 115200 -ospeed 115200 -F /dev/ttyS0

                                     在开发机上 执行 cat /dev/ttyS0    

                                     在测试机上 执行 echo "12345" < /dev/ttyS0

                                     如果在开发机上能看到 12345表示两台机器连通

          b.内核编译:在开发机上准备好内核源码及对应的KGDB patch文件(我使用的2.6.18-92.el5)

                make menuconfig   选上KGDB

                make modules     

                make modules_install (把编译后的模块文件安装到当前系统的 /lib/moudles/××××下)

            在源码文件存放的一级目录下生成System.map文件,在arch/i386/boot下生成bzImage,把这两个文件拷贝到/boot下并重命名:

                cp System.map /boot/System.map-2.6.18-92

                cp bzImage   /boot/vmlinuz-2.6.18-92

                创建 连接: ln -s System.map-2.6.18-92 System.map

                               ln -s vmlinuz-2.6.18-92         vmlinuz

                制作initrd 文件:mkinitrd initrd-2.6.18-92 ****(****表示make modules_install时在/lib/modules下新创建的文件夹名)

          c. 启动新编译内核

             打开/boot/grub/grub.conf,这个文件就像XP里的boot.ini一样,拷贝一份

             将对应的vmlinuz... 和 initrd...改成上面步骤中准备好的 ,同时需要增加启动参数:

                   kgbwait kgdb8250=0,115200   (应该本试验中使用的KGDB patch中支持8250)

             这样修改后启动会进入等连接的状态,一般在开发机上,可以先不加kgdbwait kgdb8250....这个参数,从而让系统直接启动起来,这样可以判断新编译的内核是否正确。

          d.布置测试机

             在上步能够确保启动新内核后,将vmlinuz-2.6.18-92和initrd-26.18-92两个件弄到测试机上,并修改启动项以KGDB方式启动

          e.开始内核调试(注意内核调试与内核模块调试不是一个概念)

             在开发机上,源码路径下执行gdb ./vmlinux 进入GDB

                执行 set remotebaud 115200

                      target remote /dev/ttyS0

                如果成功后看到断点停在kgdb.c中 ,表示此时已经连接到测试器上

                输入 c 让测试机继续启动,可以随时按ctrl+c 停步测试器

                在ctrl+c 停止测试器后,便可在相要的地方增加断点,进行内核单步查看调试

        

          f.如果要是调试内核模块 例如某驱动模块 test.ko 需要在开发机上使用gdbmod来代替gdb工具

               gdbmod ./vmlinux 启动调试器后与gdb操作相同

               关键在于如何加裁被调试驱动模块的符号文件(没尝试成功,因为我想调试init函数,此时驱动还没加裁)

               网上搜到的是在开发机的gdbmod下使用,set s.....path 来增加符号文件路径,这样在测试机上执行insmod test.ko后 在开发机上的gdbmod就能够找到test.ko的符号文件,可是我没尝试成功,以后还要再试

    To be continue... (在后续的学习中不断完善)

      

  • 相关阅读:
    简单的MVC小应用
    jsp四大指令元素,三大脚本元素,八大动作元素
    servlet session管理的四种方式 --隐藏表单
    servlet session管理的四种方式--一 url重写
    创建servlet三种方式(韩顺平老师课程)
    python函数
    tcpprobe ——监听TCP信息的内核模块
    Popen的方法
    Python中执行系统命令常见的几种方法
    > /dev/null 2>&1 含义
  • 原文地址:https://www.cnblogs.com/kwseeker-bolgs/p/4458607.html
Copyright © 2020-2023  润新知