zoukankan      html  css  js  c++  java
  • 第10章 嵌入式linux的调试技术

    一、      防止函数printk降低linux性能:

    利用C语言中的编译指令(#if、#else、#endif等)。

    现在修改printk_demo驱动代码,通过编译指令定义了一个pr_debug宏,并通过修改编译指令的条件值来控制是否调用printk函数。如下:

    # if 1//此处为1,使用printk函数,为0,忽略printk函数

      #define pr_debug(x,…)  do { } while(0)

    #endif

    除此之外,我们还需要了解两个知识点:1.可变参数的宏:可变参数的宏与固定参数的宏之间的区别:可变参数的宏需要通过_VA_ARGS_宏【不支持可变参数个数为0的情况】获取可变参数的宏的可变参数。定义可变参数宏与定义可变参数函数的方法相同,都使用3个点(…)来表示可变参数,可变参数必须是宏和函数最后的参数。

    二、      通过虚拟文件系统(/proc)进行数据交互:

    必要性:在linux文件系统中,/proc经常被用来作为内核空间进行数据交互的工具。/proc是虚拟文件系统,也就是说,/proc并不是真正的文件系统,而是内存映射。所有读写/proc的操作军事对内存读写的操作。所以读写/proc文件系统的速度远比读写/dev要快。因此,/proc文件系统也可作为linux驱动与用户空间程序交互的工具。

    很多信息就是通过/proc文件系统由内核空间的程序向外届提供的。例如:当前系统内存资源就是通过/proc/meminfo文件读取的,读者可以使用如下命令:查看/proc/meminfo文件的内容:Cat /proc/meminfo.我们可以通过执行free命令看看显示的信息是否和meminfo文件中的部分内容相匹配。

    在linux驱动程序中可以使用内核函数在/proc目录中创建和删除虚拟文件,也可以建立和删除虚拟目录。

    1. 1. create_proc_entry 创建proc 文件 
      struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,struct proc_dir_entry *parent);

    name: 要创建的文件名称;

    mode: 该文件的保护掩码;

    parent: 确定文件所在目录,如果置NULL ,则位置为/proc 下。

    1. 2. proc_mkdir 创建目录

    /* 该函数在父目录parent 下创建一个目录name* */

    struct proc_dir_entry * proc_mkdir (const char *name,struct proc_dir_entry *parent);

    @name : 要创建的目录名

    @parent : 这个目录的父目录

    3.remove_proc_entry 删除文件或目录

    /* 这个函数从proc 文件系统中删除一个文件或目录。

    * 注意:1 .是通过参数name ,而不是通过创建时返回的指针来删除的。

    * 2 .该函数不会递归删除目录下的文件。

    * 3 .data 变量保存了分配的内存,要先释放对应内存,再删除该文件。

    * */

    void remove_proc_entry (const char *name,struct proc_dir_entry *parent);

    @name : 要删除的文件或目录名

    @parent : 所在的父目录 

     4.create_proc_read_entry 创建只读proc 文件

    struct proc_dir_entry * create_proc_read_entry (const char

    *name,mode_t mode,struct proc_dir_entry *parent,read_proc_t*

    read_proc,void *data);

    @name : 要创建的文件名

    @mode : 要创建的文件的属性 默认0755

    @parent : 这个文件的父目录

    @read_proc : 当用户读这个文件时,内核调用的函数

    @data : 传给read_proc 的参数

    注意:删除虚拟文件目录之前,要先删除目录中的虚拟文件。

    执行build.sh脚本文件,会将proc_demo驱动安装在Ubuntu Linux、开发板或Android虚拟机上。然后执行下面的命令查看/proc/proc_demo目录中的内容。

    Ls –al /proc/proc_demo/bin2dec

    Cat /proc/proc_demo/bin2dec

    Cat /proc_demo/readonly

    三、      调试工具:

    1. 用gdb调试用户空间程序:

    Gdb可以跟踪调试用户空间的程序。

    对于一个用于测试的可执行程序(gdb_debug.c),我们可以直接运行build.sh脚本文件,但注意加上命令参数-g,完整的编译命令如下:

    #gcc –static –g –o gdb_debug /root/drivers/debug/gdb_debug.c

    现在使用下面的命令来调试:

    Gdb gdb_debug

    Gdb包含的命令:

    1>         quit:用于退出gdb调试界面

    2>          list:用于列出程序中的代码。有三种调用格式:list:显示上一次调用list命令输出的最后一行后面的10行。 list-: 显示上一次调用list命令输出的第一行前面的10行,第一次调用list命令什么都不会显示。list n:显示第n行附近的10行,一般会显示第n行前面5 行和后面4行,加上第n行,正好是10行。

    3>         Break n:将指定行设置为断点,n表示行号

    4>         Clear n:清除指定行的断点。

    5>         Tbreak n:将指定行设置为断点,断点只能使用一次,使用完成后自动清零。

    6>         Cont/continue:跳过当前断点继续执行。[cont:跳过当前断点继续执行;cont n:跳过n次断点继续前行]

    7>         Next:继续执行下面的语句,但跳过这程序。等价于step over。[同上有两种格式next 及next n]

    8>         Nexti:单步执行语句,和next的区别:它会跟踪到子程序的内部,但不打印出子程序内部的语句。

    9>         Print var_name:查看变量值.

    1. 用gdbserver远程调试用户空间程序:

    1.与GDB的区别:gdb用于PC上进行测试,而gdbserver测试运行于开发板、手机、Android模拟器上。

    2.在开发板上使用gdbserver打开测试程序,然后通过串口、有线、无线网络可以在PC上进行测试。

    3.第一步:进入Android模拟器的终端,然后进入data/local目录,并执行如下命令:gdbserver :4321 ./gdb_debug启动gdbserver监听程序。其中4321表示使用本机的4321端口号进行监听。

      第二步:开启另一个Linux终端,将外部访问模拟器的4321端口的数据包转发到Android模拟器内部的4321端口:adb –s emulator-5544 forword tcp:4321[有多个Android设备时要加-s命令行参数指定具体的Android设备]。

    第二个方法[映射端口]:1.进入telent:telent localhost 5554 2.映射端口:redir add tcp:4321:4321

    第三步:进入gdb控制台:arm-none-linux-guneabi-gdb gdb_debug

    第四步:连接Android模拟器:(gdb) target remote localhost:4321

                最后:输入gdb命令进行调试。

            通过IP方式连接开发板上的gdbserver:1.gdbserver localhost:4321 ./gdb_debug  2.在linux终端的gdb控制台链接开发板的gdbsrever:(gdb) target remote 192.168.17.103 ./gdb_debug.

            通过串口方式:对应的应该是:1.gdbserver /dev/s3c2410_serial0 ./gdb_debug  2.(gdb) target remote /dev/ttyUSB0

    1. 用kgdb远程调试内核程序:

    Kgdb除了提供类似printk函数的日志输出功能,还允许开发人员直接在PC上通过GDB链接目标设备。

    Kgdb包含两个部分:kgdb内核和一套链接接口【目前支持串口tty设备链接和以太网连接】。其中串口连接需要通过内核参数kgdboc指定要链接的串口tty设备:以太网连接通过内核参数kgdboc指定IP和端口号。

    要想用kgdb调试内核,首先需要配置linux内核。使用make menuconfig命令进入Linux内核的配置菜单。【Kernel hacking--àKGDB:kernel debugger】

         配置内核参数时,这些参数通知Linux内核要如何进行调试。假设要通过USB转COM口数据线进行调试,需要将kgdboc参数值折为ttyUSB0,传输效率为115200,一般会指定kdbwait。这些参数需要在S3C开发板过程中按回车进入Uboot模式,然后使用setenv命令设置Linux内核的启动参数,然后使用saveenv和rest命令保存和重新启动Linux内核。

    在设置完成后,主机就可以使用gdb命令像调试普通嵌入式应用程序一样调试Linux内核,执行的命令如下:

    #gdb  ./vmlinux

    完成后,使用如下的命令设置传输速率和连接也要调试的Linux内核。

    (gdb) set remoteband 115200

    (gdb) target remote /dev/ttyUSB0

    最后使用各种gdb命令进行Linux内核调试。

  • 相关阅读:
    apache 访问出现403 Forbidden
    linux下用Apache一个IP多个域名建虚拟主机
    利用xargs 可以一次性卸载到位
    linux安装包地址备忘
    ii7安装php
    基于jQuery的对象切换插件:soChange 1.5 (点击下载)
    phpMyAdmin 缺少 mysqli 扩展。请检查 PHP 配置
    Android中的自动朗读(TTS)
    Android中的手势
    Android中的SQLiteOpenHelper类
  • 原文地址:https://www.cnblogs.com/beatrice/p/5656055.html
Copyright © 2011-2022 走看看