Linux裝置驅動程式調式 GDB調式 核心調式KDB調式

來源:互聯網
上載者:User

 今天進入《Linux裝置驅動程式(第3版)》第四章調試技術的學習。
一、核心中的調試支援
在前面已經建議過:學習編寫驅動程式要構建安裝自己的核心(標準主線核心)。最重要的原因之一是:核心開發人員已經建立了多項用於調試的功能。但是由於這些功能會造成額外的輸出,並導致能下降,因此發行版廠商通常會禁止發行版核心中的調試功能。
為了實現核心調試,我在核心配置上增加了幾項:
  Kernel hacking  --->     
        

  • Magic SysRq key
            
  • Kernel debugging
            
  •    Debug slab memory allocations  
            
  •    Spinlock and rw-lock debugging: basic checks
            
  •    Spinlock debugging: sleep-inside-spinlock checking
            
  •    Compile the kernel with debug info  
            
  • Magic SysRq key
    Device Drivers  --->  
            Generic Driver Options  --->
             
  • Driver Core verbose debug messages
    General setup  --->
          
  • Configure standard kernel features (for small systems)  --->
             
  •    Load all symbols for debugging/ksymoops
    書上介紹的還有其他配置,有的我不需要,或是s3c2440不支援,菜單裡看不見。
    二、通過列印調試
    (1)printk
    首先,printk有8個loglevel,定義在中:
    #define    KERN_EMERG    ""    /* system is unusable           */
    #define    KERN_ALERT    ""   /* action must be taken immediately*/
    #define    KERN_CRIT    ""    /* critical conditions    */
    #define    KERN_ERR    ""    /* error conditions            */
    #define    KERN_WARNING    ""    /* warning conditions   */
    #define    KERN_NOTICE    ""    /* normal but significant condition */
    #define    KERN_INFO    ""    /* informational            */
    #define    KERN_DEBUG    ""    /* debug-level messages   */
    未指定優先順序的預設層級定義在/kernel/printk.c中:
    #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
    當優先順序的值小於console_loglevel這個整數變數的值,資訊才能顯示出來。而console_loglevel的初始值DEFAULT_CONSOLE_LOGLEVEL也定義在/kernel/printk.c中:
    #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
    而在運行是改變console_loglevel的程式(《Linux裝置驅動程式(第3版)》提供)如下:
    #include stdio.h>
    #include stdlib.h>
    #include string.h>
    #include errno.h>
    #define __LIBRARY__ /* _syscall3 and friends are only available through this */
    #include linux/unistd.h>
    /* define the system call, to override the library function */
    _syscall3(int, syslog, int, type, char *, bufp, int, len);
    int main(int argc, char **argv)
    {
        int level;
        if (argc==2) {
        level = atoi(argv[1]); /* the chosen console */
        } else {
            fprintf(stderr, "%s: need a single arg\n",argv[0]); exit(1);
        }
        if (syslog(8,NULL,level)  0) {
            fprintf(stderr,"%s: syslog(setlevel): %s\n",
                    argv[0],strerror(errno));
            exit(1);
        }
        exit(0);
    }
    最關鍵的“syslog(8,NULL,level)”語句我不理解,沒有找到相關資料。但是通過在ARM9板上的實驗表明:程式是ok的!我用Hello world模組做了實驗,現象和書上的一致。
    [Tekkaman2440@SBC2440V4]#cd /tmp/
    [Tekkaman2440@SBC2440V4]#./setlevel 1
    [Tekkaman2440@SBC2440V4]#cd /lib/modules/
    [Tekkaman2440@SBC2440V4]#insmod hello.ko
    [Tekkaman2440@SBC2440V4]#rmmod hello
    [Tekkaman2440@SBC2440V4]#cd /tmp/
    [Tekkaman2440@SBC2440V4]#./setlevel 7
    [Tekkaman2440@SBC2440V4]#cd /lib/modules/
    [Tekkaman2440@SBC2440V4]#insmod hello.ko
    Hello, Tekkaman Ninja !
    [Tekkaman2440@SBC2440V4]#rmmod hello
    Goodbye, Tekkaman Ninja !
    Love Linux !Love ARM ! Love KeKe !
    [Tekkaman2440@SBC2440V4]#
    還有通過對/proc/sys/kernel/printk的訪問來改變console_loglevel的值:
    [Tekkaman2440@SBC2440V4]#echo 1 > /proc/sys/kernel/printk
    [Tekkaman2440@SBC2440V4]#cat /proc/sys/kernel/printk
    1       4       1       7
    [Tekkaman2440@SBC2440V4]#insmod hello.ko
    [Tekkaman2440@SBC2440V4]#rmmod hello
    [Tekkaman2440@SBC2440V4]#echo 7 > /proc/sys/kernel/printk
    [Tekkaman2440@SBC2440V4]#cat /proc/sys/kernel/printk7       4       1       7
    [Tekkaman2440@SBC2440V4]#insmod hello.ko
    Hello, Tekkaman Ninja !
    [Tekkaman2440@SBC2440V4]#rmmod hello
    Goodbye, Tekkaman Ninja !
    Love Linux !Love ARM ! Love KeKe !
    四個數位含義:當前的loglevel、預設loglevel、最小允許的loglevel、引導時的預設loglevel。
    為了方便的開啟和關閉調試資訊,《Linux裝置驅動程式(第3版)》提供以下源碼:
    /* Macros to help debugging */
    #undef PDEBUG /* undef it, just in case */
    #ifdef SCULL_DEBUG
    # ifdef __KERNEL__
         /* This one if debugging is on, and kernel space */
    # define PDEBUG(fmt, args...) printk( KERN_DEBUG "scull: " fmt, ## args)
    # else     /* This one for user space */
    # define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
    # endif
    #else
    # define PDEBUG(fmt, args...) /* not debugging: nothing */
    #endif
    #undef PDEBUGG
    #define PDEBUGG(fmt, args...) /* nothing: it's a placeholder */
    Makefile中要添加的語句:
    # Comment/uncomment the following line to disable/enable debugging
    DEBUG = y
    # Add your debugging flag (or not) to CFLAGS
    ifeq ($(DEBUG),y)
      DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
    else
      DEBFLAGS = -O2
    endif
    CFLAGS += $(DEBFLAGS)
    為了避免printk重複輸出過快而阻塞系統,核心使用以下函數跳過部分輸出:
    int printk_ratelimit(void);
    典型的應用如下:
    if (printk_ratelimit( ))
        printk(KERN_NOTICE "The printer is still on fire\n");
    可以通過修改/proc/sys/kernel/printk_ratelimit(重開資訊前應等待的秒數)和/proc/sys/kernel/printk_ratelimit_burst(在速度限制前可接受的資訊數)來定製printk_ratelimit的行為。
    Linux還提供了列印裝置編號的宏(在中定義):
    int print_dev_t(char *buffer, dev_t dev);
    char *format_dev_t(char *buffer, dev_t dev);
    兩個函數的唯一區別是:print_dev_t返回列印字元數,format_dev_t返回緩衝區指標。注意緩衝區char *buffer的大小應至少有20B。
                   
                    三、通過查詢調試
    多數情況中,擷取相關資訊的最好方法是在需要的時候才去查詢系統資訊,而不是持續不斷地產生資料。
    使用/proc檔案系統
    /proc檔案系統是一種特殊的、由軟體建立的檔案系統,核心使用他向外界匯出資訊。/proc下面的每個檔案都綁定於一個核心功能,使用者讀取其中的檔案時,該函數動態組建檔案的內容。如以前用過的:
    [Tekkaman2440@SBC2440V4]#cat /proc/devices
    Character devices:
      1 mem
      2 pty
      3 ttyp
      4 /dev/vc/0
      4 tty
      4 ttyS
      5 /dev/tty
      5 /dev/console
      5 /dev/ptmx
      7 vcs
    10 misc
    13 input
    14 sound
    81 video4linux
    89 i2c
    90 mtd
    116 alsa
    128 ptm
    136 pts
    180 usb
    189 usb_device
    204 s3c2410_serial
    252 scull
    253 usb_endpoint
    254 rtc
    Block devices:
      1 ramdisk
    256 rfd
      7 loop
    31 mtdblock
    93 nftl
    96 inftl
    179 mmc
    使用/proc的模組必須包含,而使用seq_file介面要包含。
    具體的應用方法看來源程式、做實驗更有效果。
    至於其他的調試方法,如gdb、LTT、SysRq等方法,在其他的書籍,如:《嵌入式Linux系統開發技術詳解-基於ARM》、《構建嵌入式Linux系統》等,上講解的更為詳細,以後專門花時間研究。
    四、源碼實驗
    模組程式連結:
    模組程式
    模組測試程式連結:
    模組測試程式
    實驗現象:
    [Tekkaman2440@SBC2440V4]#cd /lib/modules/
    [Tekkaman2440@SBC2440V4]#insmod scull_debug.ko scull_nr_devs=1 scull_quantum=6 scull_qset=2
    [Tekkaman2440@SBC2440V4]#cd /tmp/
    [Tekkaman2440@SBC2440V4]#./scull_test
    write  code=6
    write  code=6
    write  code=6
    write  code=2
    read  code=6
    read  code=6
    read  code=6
    read  code=2
    [0]=0 [1]=1 [2]=2 [3]=3 [4]=4
    [5]=5 [6]=6 [7]=7 [8]=8 [9]=9
    [10]=10 [11]=11 [12]=12 [13]=13 [14]=14
    [15]=15 [16]=16 [17]=17 [18]=18 [19]=19
    [Tekkaman2440@SBC2440V4]#cd /proc/
    [Tekkaman2440@SBC2440V4]#ls
    1              751            cmdline        kallsyms       stat
    2              769            cpu            kmsg           swaps
    3              77             cpuinfo        loadavg        sys
    4              778            crypto         locks          sysrq-trigger
    5              779            devices        meminfo        sysvipc
    59             78             diskstats      misc           timer_list
    6              781            driver         modules        tty
    60             783            execdomains    mounts         uptime
    63             785            filesystems    mtd            version
    65             79             fs             net            vmstat
    707            80             ide            partitions     yaffs
    708            819            interrupts     scullmem       zoneinfo
    709            asound         iomem          scullseq
    710            buddyinfo      ioports        self
    742            bus            irq            slabinfo
    [Tekkaman2440@SBC2440V4]#cat scullmem
    Device 0: qset 2, q 6, sz 20
      item at c071ebd4, qset at c071ef7c
      item at c071ef14, qset at c071eee0
           0: c071eeac
           1: c071ee78
    [Tekkaman2440@SBC2440V4]#cat scullseq
    Device 0: qset 2, q 6, sz 20
      item at c071ebd4, qset at c071ef7c
      item at c071ef14, qset at c071eee0
           0: c071eeac
           1: c071ee78
    [Tekkaman2440@SBC2440V4]#rmmod scull_debug
    [Tekkaman2440@SBC2440V4]#ls
    1              742            buddyinfo      iomem          self
    2              751            bus            ioports        slabinfo
    3              769            cmdline        irq            stat
    4              77             cpu            kallsyms       swaps
    5              778            cpuinfo        kmsg           sys
    59             779            crypto         loadavg        sysrq-trigger
    6              78             devices        locks          sysvipc
    60             781            diskstats      meminfo        timer_list
    63             783            driver         misc           tty
    65             785            execdomains    modules        uptime
    707            79             filesystems    mounts         version
    708            80             fs             mtd            vmstat
    709            824            ide            net            yaffs
    710            asound         interrupts     partitions     zoneinfo
  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.