乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Linux內(nèi)核調(diào)試

       趙帥蹲守圖書(shū)館 2014-02-16

         悄悄地進(jìn)入Linux內(nèi)核調(diào)試(一)

         本文基址:http://blog.csdn.net/cugxueyu/archive/2007/12/21/1957740.aspx

      調(diào)試工作艱苦,是內(nèi)核級(jí)開(kāi)發(fā)區(qū)別于用戶(hù)級(jí)開(kāi)發(fā)的一個(gè)顯著特點(diǎn)。
      駕馭內(nèi)核調(diào)試的能力,很大程度上取決于經(jīng)驗(yàn)和對(duì)整個(gè)操作系統(tǒng)的把握。
       
      一、調(diào)試前的準(zhǔn)備
         內(nèi)核級(jí)bug具有行為不可靠定義不清晰或者說(shuō)很難再現(xiàn)的諸多特定,為內(nèi)核級(jí)的bug跟蹤和調(diào)試帶來(lái)了很大的困難。
         ※ 對(duì)于一些定義不清楚地bug,問(wèn)題的關(guān)鍵就是找到bug的源頭,很多時(shí)候,當(dāng)你精確地重現(xiàn)一個(gè)bug的時(shí)候,你就離成功不遠(yuǎn)了。
       
      二、內(nèi)核中的bug
         從隱藏在源代碼中的錯(cuò)誤到展現(xiàn)在目擊者面前的bug,其發(fā)作往往是一系列連鎖反應(yīng)的事件才可能出發(fā)的。
         雖然內(nèi)核調(diào)試有一定的困難,但是通過(guò)你的努力和理解,說(shuō)不定你會(huì)喜歡上這樣的挑戰(zhàn)。
       
      三、printk( )
       內(nèi)核提供的格式化打印函數(shù)。
       1、printk函數(shù)的健壯性
          健壯性是printk最容易被接受的一個(gè)特質(zhì),幾乎在任何地方,任何時(shí)候內(nèi)核都可以調(diào)用它(中斷上下文、進(jìn)程上下文、持有鎖時(shí)、多處理器處理時(shí)等)。
         ※ 在系統(tǒng)啟動(dòng)過(guò)程中,終端初始化之前,在某些地方是不能調(diào)用的。
       
       2、記錄等級(jí)
          printk函數(shù)可以指定一個(gè)記錄級(jí)別,內(nèi)核根據(jù)這個(gè)級(jí)別來(lái)判斷是否在終端上打印消息。
          記錄級(jí)別定義在<linux/kernel.h>中:
          
      #define    KERN_EMERG    "<0>"   /* system is unusable */
      #define    KERN_ALERT    "<1>"    /* action must be taken immediately    */
      #define    KERN_CRIT        "<2>"    /* critical conditions */
      #define    KERN_ERR        "<3>"    /* error conditions    */
      #define    KERN_WARNING    "<4>"    /* warning conditions */
      #define    KERN_NOTICE   "<5>"    /* normal but significant condition    */
      #define    KERN_INFO        "<6>"    /* informational */
      #define    KERN_DEBUG    "<7>"   /* debug-level messages    */
       
       調(diào)用方式:printk(KER_DEBUG “This is a debug notice!/n”);
       內(nèi)核用這個(gè)指定的紀(jì)錄等級(jí)和當(dāng)前終端的紀(jì)錄等級(jí)console_loglevel比較,來(lái)決定是不是向終端打印。
       
       關(guān)于< linux/kernel.h >的console_loglevel 定義:
       #define console_loglevel (console_printk[0])
       <printk.c>定義:
       int console_printk[4] = {
                 DEFAULT_CONSOLE_LOGLEVEL,  /* console_loglevel */
                 DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */
                 MINIMUM_CONSOLE_LOGLEVEL,  /* minimum_console_loglevel */
                 DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */
       };
       
       3、記錄緩沖區(qū)
         內(nèi)核消息都被保存在一個(gè)LOG_BUF_LEN大小的環(huán)形隊(duì)列中。
         關(guān)于LOG_BUF_LEN定義:
         #define __LOG_BUF_LEN     (1 << CONFIG_LOG_BUF_SHIFT)
         ※ 變量CONFIG_LOG_BUF_SHIFT在內(nèi)核編譯時(shí)由配置文件定義,對(duì)于i386平臺(tái),其值定義如下(在linux26/arch/i386/defconfig中):
         CONFIG_LOG_BUF_SHIFT=18
       
         記錄緩沖區(qū)操作
         ①、消息被讀出到用戶(hù)空間時(shí),此消息就會(huì)從環(huán)形隊(duì)列中刪除。
         ②、當(dāng)消息緩沖區(qū)滿時(shí),如果再有printk()調(diào)用時(shí),新消息將覆蓋隊(duì)列中的老消息。
         ③、在讀寫(xiě)環(huán)形隊(duì)列時(shí),同步問(wèn)題很容易得到解決。
         ※ 這個(gè)紀(jì)錄緩沖區(qū)之所以稱(chēng)為環(huán)形,是因?yàn)樗淖x寫(xiě)都是按照環(huán)形隊(duì)列的方式進(jìn)行操作的。
       
       4、syslogd和klogd
         在標(biāo)準(zhǔn)的Linux系統(tǒng)上,用戶(hù)空間的守護(hù)進(jìn)程klogd從紀(jì)錄緩沖區(qū)中獲取內(nèi)核消息,再通過(guò)syslogd守護(hù)進(jìn)程把這些消息保存在系統(tǒng)日志文件中。klogd進(jìn)程既可以從/proc/kmsg文件中,也可以通過(guò)syslog()系統(tǒng)調(diào)用讀取這些消息。默認(rèn)情況下,它選擇讀取/proc方式實(shí)現(xiàn)。klogd守護(hù)進(jìn)程在消息緩沖區(qū)有新的消息之前,一直處于阻塞狀態(tài)。一旦有新的內(nèi)核消息,klogd被喚醒,讀出內(nèi)核消息并進(jìn)行處理。默認(rèn)情況下,處理例程就是把內(nèi)核消息傳給syslogd守護(hù)進(jìn)程。
         syslogd守護(hù)進(jìn)程一般把接收到的消息寫(xiě)入/var/log/messages文件中。不過(guò),還是可以通過(guò)/etc/syslog.conf文件來(lái)進(jìn)行配置,可以選擇其他的輸出文件。
        圖1 X光了此過(guò)程:
       
       
      四、OOPS
       OOPS(也稱(chēng) Panic)消息包含系統(tǒng)錯(cuò)誤的細(xì)節(jié),如 CPU 寄存器的內(nèi)容等。是內(nèi)核告知用戶(hù)有不幸發(fā)生的最常用的方式。
       內(nèi)核只能發(fā)布OOPS,這個(gè)過(guò)程包括向終端上輸出錯(cuò)誤消息,輸出寄存器保存的信息,并輸出可供跟蹤的回溯線索。通常,發(fā)送完OOPS之后,內(nèi)核會(huì)處于一種不穩(wěn)定的狀態(tài)。
       OOPS的產(chǎn)生有很多可能原因,其中包括內(nèi)存訪問(wèn)越界或非法的指令等。
       ※ 作為內(nèi)核的開(kāi)發(fā)者,必定將會(huì)經(jīng)常處理OOPS。
       ※ OOPS中包含的重要信息,對(duì)所有體系結(jié)構(gòu)的機(jī)器都是完全相同的:寄存器上下文和回溯線索(回溯線索顯示了導(dǎo)致錯(cuò)誤發(fā)生的函數(shù)調(diào)用鏈。
       
       1、ksymoops
          在 Linux 中,調(diào)試系統(tǒng)崩潰的傳統(tǒng)方法是分析在發(fā)生崩潰時(shí)發(fā)送到系統(tǒng)控制臺(tái)的 Oops 消息。一旦您掌握了細(xì)節(jié),就可以將消息發(fā)送到 ksymoops 實(shí)用程序,它將試圖將代碼轉(zhuǎn)換為指令并將堆棧值映射到內(nèi)核符號(hào)。
          ※ 如:回溯線索中的地址,會(huì)通過(guò)ksymoops轉(zhuǎn)化成名稱(chēng)可見(jiàn)的函數(shù)名。
          圖2X光了格式化 Oops 消息過(guò)程:
         
       
          ksymoops需要幾項(xiàng)內(nèi)容:Oops 消息輸出、來(lái)自正在運(yùn)行的內(nèi)核的 System.map 文件,還有 /proc/ksyms、vmlinux 和 /proc/modules。
      關(guān)于如何使用 ksymoops,內(nèi)核源代碼 /usr/src/linux/Documentation/oops-tracing.txt 中或 ksymoops 手冊(cè)頁(yè)上有完整的說(shuō)明可以參考。Ksymoops 反匯編代碼部分,指出發(fā)生錯(cuò)誤的指令,并顯示一個(gè)跟蹤部分表明代碼如何被調(diào)用。
       
       2、kallsyms
          開(kāi)發(fā)版2.5內(nèi)核引入了kallsyms特性,它可以通過(guò)定義CONFIG_KALLSYMS編譯選項(xiàng)啟用。該選項(xiàng)可以載入內(nèi)核鏡像所對(duì)應(yīng)的內(nèi)存地址的符號(hào)名稱(chēng)(即函數(shù)名),所以?xún)?nèi)核可以打印解碼之后的跟蹤線索。相應(yīng),解碼OOPS也不再需要System.map和ksymoops工具了。另外,
      這樣做,會(huì)使內(nèi)核變大些,因?yàn)榈刂穼?duì)應(yīng)符號(hào)名稱(chēng)必須始終駐留在內(nèi)核所在內(nèi)存上。
          #cat /proc/kallsyms
           c0100240   T       _stext
           c0100240   t       run_init_process
           c0100240   T      stext
           c0100269   t       init
              …
       
      五、內(nèi)核調(diào)試配置選項(xiàng)
       在編譯內(nèi)核的時(shí)候,為了方便調(diào)試和測(cè)試代碼,內(nèi)核提供了許多配置選項(xiàng)。
       ※  啟用選項(xiàng)例如:
         slab layer debugging(slab層調(diào)試選項(xiàng))、high-memory debugging(高端內(nèi)存調(diào)試選項(xiàng))、I/O mapping debugging(I/O映射調(diào)試選項(xiàng))、spin-lock debugging(自旋鎖調(diào)試選項(xiàng))、stack-overflow checking(棧溢出檢查選項(xiàng))和sleep-inside-spinlock checking(自旋鎖內(nèi)睡眠選項(xiàng))等。
       
      1、調(diào)試原子操作
       從內(nèi)核2.5開(kāi)發(fā),為了檢查各類(lèi)由原子操作引發(fā)的問(wèn)題,內(nèi)核提供了極佳的工具。
       內(nèi)核提供了一個(gè)原子操作計(jì)數(shù)器,它可以配置成,一旦在原子操作過(guò)程中,進(jìn)城進(jìn)入睡眠或者做了一些可能引起睡眠的操作,就打印警告信息并提供追蹤線索。
       所以,包括在使用鎖的時(shí)候調(diào)用schedule(),正使用鎖的時(shí)候以阻塞方式請(qǐng)求分配內(nèi)存等,各種潛在的bug都能夠被探測(cè)到。
       下面這些選項(xiàng)可以最大限度地利用該特性:
       CONFIG_PREEMPT = y
       CONFIG_DEBUG_KERNEL = y
       CONFIG_KLLSYMS = y
       CONFIG_SPINLOCK_SLEEP = y
       
      六、引發(fā)bug并打印信息
       1、一些內(nèi)核調(diào)用可以用來(lái)方便標(biāo)記bug,提供斷言并輸出信息。最常用的兩個(gè)是BUG()BUG_ON()
       定義在<include/asm-generic>中:

      #ifndef HAVE_ARCH_BUG
      #define BUG() do { 
          printk(
      "BUG: failure at %s:%d/%s()! ", __FILE__, __LINE__, __FUNCTION__); 
          panic(
      "BUG!");   /* 引發(fā)更嚴(yán)重的錯(cuò)誤,不但打印錯(cuò)誤消息,而且整個(gè)系統(tǒng)業(yè)會(huì)掛起 */
      while (0)
      #endif

      #ifndef HAVE_ARCH_BUG_ON
          
      #define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0)
      #endif
        
      當(dāng)調(diào)用這兩個(gè)宏的時(shí)候,它們會(huì)引發(fā)OOPS,導(dǎo)致棧的回溯和錯(cuò)誤消息的打印。
      ※ 可以把這兩個(gè)調(diào)用當(dāng)作斷言使用,如:BUG_ON(bad_thing);
       
       2、dump_stack()
          有些時(shí)候,只需要在終端上打印一下棧的回溯信息來(lái)幫助你調(diào)試。這時(shí)可以使用dump_stack()。這個(gè)函數(shù)只在終端上打印寄存器上下文和函數(shù)的跟蹤線索。
          if (!debug_check) {
              printk(KERN_DEBUG “provide some information…/n”);
              dump_stack();
          }
       備注:大部分內(nèi)容引自《Linux內(nèi)核設(shè)計(jì)實(shí)現(xiàn) - 2版》

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多