<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      《Linux內核設計與實現》讀書筆記(十八)- 內核調試

      內核調試的難點在于它不能像用戶態程序調試那樣打斷點,隨時暫停查看各個變量的狀態。

      也不能像用戶態程序那樣崩潰后迅速的重啟,恢復初始狀態。

       

      用戶態程序和內核交互,用戶態程序的各種狀態,錯誤等可以由內核來捕獲并顯示。

      而內核是直接和硬件交互的,內核出錯之后整個系統就無法正常運行了,所以要想熟練的進行內核調試,

      首先要熟悉內核已經給我們提供的工具,然后實實在在的去做一些內核功能的開發,在開發的過程中不斷熟悉內核代碼,增加內核調試的經驗。

       

      主要內容:

      • 內核調試的難點
      • 內核調試的工具和方法
      • 總結

       

      1. 內核調試的難點

      內核調試的難點大致有以下幾個:

      1. 重現bug困難 - 如果能夠重現一個bug, 相當于成功了一半. (特別是有些bug和硬件相關, 執行幾百萬次之后才有一次錯誤)
      2. 調試風險比較大 - 稍有不慎, 即造成系統崩潰
      3. 定位bug的初始版本困難 - 內核版本更新很快, 很難確定bug是在那個版本開始出現的

       

      2. 內核調試的工具和方法

      內核調試雖然困難, 但同時也極具挑戰性, 如果能夠解決一個困擾大家多時的內核bug, 那將會給自己帶來極大的成就感. :)

      而且, 隨著內核的不斷發展, 內核調試的手段和方法也在不斷進步, 下面是書中提到的一些常用的調試手段.

       

      2.1 輸出 LOG

      輸出LOG不光是內核調試, 即使是在用戶態程序的調試中, 也是經常使用的一個調試手段.

      通過在可疑的代碼周圍加上一些LOG輸出, 可以準確的了解bug發生前后的一些重要信息.

       

      2.1.1 LOG等級

      linux內核中輸出LOG的函數是 printk (語法和printf幾乎雷同, 唯一的區別是printk可以指定日志級別)

      printk之所以好用, 就在與它隨時都可以被調用, 沒有任何限制條件.

      printk的輸出日志級別如下:

      等級

      描述

      KERN_EMERG 一個緊急情況
      KERN_ALERT 一個需要立即被注意到的錯誤
      KERN_CRIT 一個臨界情況
      KERN_ERR 一個錯誤
      KERN_WARNING 一個警告
      KERN_NOTICE 一個普通的, 不過也有可能需要注意的情況
      KERN_INFO 一條非正式的消息
      KERN_DEBUG 一條調試信息--一般是冗余信息

       

      輸出示例:

      printk(KERN_WARNING "This is a warning!\n");
      printk(KERN_DEBUG "This is a debug notice!\n");

       

      2.1.2 LOG記錄

      標準linux系統上, printk 輸出log之后, 由用戶空間的守護進程klogd從緩沖區中讀取內核消息, 然后再通過syslogd守護進程將它們保存在系統日志文件中.

      syslogd 將接受到的所有內核消息添加到一個文件中, 該文件默認為: /var/log/dmesg (系統Centos6.4 x86_64)

       

      PS. 上篇博客中的內核模塊的輸出LOG, 都可以在 /var/log/dmesg 中看到

       

      2.2 oops

      oopss是個擬聲詞, 類似 "哎喲" 的意思. 它是內核通知用戶有不幸發生的最常用方式.

      觸發一個oops很簡單, 其實只要在上篇博客中的那些內核模塊示例中隨便找一個, 里面加上一段給未初始化的指針賦值的代碼, 就能觸發一個oops

       

      oops中包含錯誤發生時的一些重要信息(比如, 寄存器上下文和回溯線索), 對調試bug很有幫助!

       

      調試內核時, 還可以開啟內核編譯參數中的各種和內核調試相關的選項, 那樣還可以給我們提供內核崩潰時的一些額外信息.

       

      2.3 主動觸發bug

      調試中有時將某些情況下標記為bug, 執行到這些情況時, 提供斷言并輸出信息.

      BUG 和 BUG_ON 就是2個可以主動觸發oops的內核調用.

       

      在不應該被執行到的地方使用 BUG 或者 BUG_ON 來捕獲.

      比如:

      if (bad_thing)
          BUG();
      // 或者
      BUG_ON(bad_thing);

       

      如果想要觸發更為嚴重的錯誤, 可以使用 panic() 函數

      比如:

      if (terrible_thing)
          panic("terrible thing is %ld\n", terrible_thing);

       

      此外, 還有dump_stack 函數可以打印寄存器上下文和回溯信息.

      比如:

      if (!debug_check) {
          printk(KERN_DEBUG "provide some information...\n");
          dump_statck();
      }

       

      2.4 神奇的系統請求鍵

      這個系統請求鍵之所以神奇, 在于它可以在一個快掛了的系統上輸出一些有用的信息.

      這個按鍵一般就是標準鍵盤上的 [SysRq] 鍵 (就在 F12 鍵右邊, 其實就是windows中截整個屏幕的按鍵)

      單獨按那個鍵相當于截屏, 按住 ALT + [SysRq] = [SysRq]的功能

       

      啟用這個鍵的功能有2個方法:

      • 開啟內核編譯選項 : CONFIG_MAGIC_SYSRQ
      • 動態啟用: echo 1 > /proc/sys/kernel/sysrq

       

      支持 SysRq 的命令如下: (注意要在控制臺界面下使用這個鍵, 比如通過 ALT+CTRL+F2 進入一個控制臺界面)

      主要命令

      描述

      SysRq-b 重新啟動機器
      SysRq-e 向init以外的所有進程發送SIGTERM信號
      SysRq-h 在控制臺顯示SysRq的幫助信息
      SysRq-i 向init以外的所有進程發送SIGKILL信號
      SysRq-k 安全訪問鍵:殺死這個控制臺上的所有程序
      SysRq-l 向包括init的所有進程發送SIGKILL信號
      SysRq-m 把內存信息輸出到控制臺
      SysRq-o 關閉機器
      SysRq-p 把寄存器信息輸出到控制臺
      SysRq-r 關閉鍵盤原始模式
      SysRq-s 把所有已安裝文件系統都刷新到磁盤
      SysRq-t 把任務信息輸出到控制臺
      SysRq-u 卸載所有已加載文件系統

       

      2.5 內核調試器 gdb和kgdb

      linux內核的調試器可以使用 gdb或者kgdb, 配置比較麻煩, 準備實際用調試的時候再去試試效果如何..

       

      2.6 探測系統

      下面一些方法是在修改內核后, 用來試探內核反應的小技巧.

      2.6.1 用UID控制內核執行

      比如在內核中加入了新的特性, 為了測試特性, 可以用UID來控制內核是否執行新特性.

      if (current->uid != 7777) {
          /* 原先的代碼 */
      } else {
         /* 新的特性 */
      }

       

      2.6.2 用條件變量控制內核執行

      也可以設置一些條件變量來控制內核是否執行某段代碼.

      條件變量可以像上篇博客中那樣, 設置在 sys 文件系統的某個文件中. 當文件中的值變化時, 通知內核執行相應的代碼.

       

      2.6.3 使用統計量觀察內核執行某段代碼的頻率

      實現思路就是在內核中的設置一個全局變量, 比如 my_count, 當內核執行到某段代碼時, 給 my_count + 1 就行.

      同時還要將 my_count 打印出來(可以用printk), 便于隨時查看它的值.

       

      2.6.4 控制內核執行某段代碼的頻率

      有時侯, 我們需要在內核發生錯誤時打印錯誤相關的信息, 如果這個錯誤不會導致內核崩潰, 并且這個錯誤每秒會發生幾百次甚至更多.

      那么, 用printk輸出的信息會非常多, 給系統造成額外的負擔.

      這時, 我們就需要想辦法控制錯誤輸出的頻率, 有2種方法:

      方法1: 隔一段時間才輸出一次錯誤

      static unsigned long prev_jiffy = jiffies;  /* 頻率限制 */
      
      if (time_after(jiffies, prev_jiffy + 2*HZ)) {  /* 輸出間隔至少 2HZ */
          prev_jiffy = jiffies;
          printk(KERN_ERR "錯誤信息....\n");
      }

       

      方法2: 輸出 N 次之后, 不再輸出(N是正整數)

      static unsigned long limit = 0;
      
      if (limit < 5) { /* 輸出5次錯誤信息后就不再輸出 */
          limit++;
          printk(KERN_ERR "錯誤信息....\n");
      }

       

      2.7 二分法查找bug發生的最初內核版本

      在內核發生了bug之后, 如果能夠知道是bug從哪個內核版本開始出現的, 那對修正這個bug會有很大的幫助.

      由于內核代碼非常龐大, 即使用二分查找法, 手工去找哪個版本開始出現bug的話, 仍然是非常耗時和繁瑣的.

       

      好在 Git 給我們提供了一個非常有用的二分搜索機制.

      git bisect start  # 開始二分搜索
      git bisect bad <bad_revision> # 指定一個bug出現的內核版本號
      git bisect good <good_revision> # 指定一個沒有bug的內核版本號, 此時git會檢測2個版本直接的隱患
      
      # 根據結果再次設置 bad 和 good 的版本號, 縮小Git檢索范圍, 直至找到可疑之處為止.

       

      2.8 社區

      當你在調試bug時用盡了一切手段仍然無濟于事時, 可以考慮求助linux社區, 求助時注意一定要描述清楚bug的狀況.

      (可以參考一下別人匯報bug的格式)

       

      linux 內核相關的郵件列表非常多: 參見 http://vger.kernel.org/vger-lists.html

      和內核開發, bug匯報相關的郵件列表參見: http://vger.kernel.org/vger-lists.html#linux-kernel (這個郵件列表非常活躍, 每天的郵件都非常多!!!)

       

      3. 總結

      linux內核調試必須要依靠大量的實踐來掌握, 僅僅靠上面介紹的一些技巧還遠遠不夠, 只有實實在在的去閱讀內核代碼, 實實在在的去修正一個個bug, 才算真正掌握內核, 真正了解內核.

      多看看之前linux內核bug的修正案例, 也是個不錯的積累經驗的方法.

       

      PS.

      對于初學者來說, 在真機上做內核開發動輒導致機器崩潰(panic), 非常麻煩. 現在的虛擬機這么強大, 建議都在虛擬機上測試linux內核修改的效果.

      我之前的關于<<Linux內核設計與實現>>筆記的博客中的代碼都是在虛擬機上運行測試的.

      posted @ 2014-01-04 09:03  wang_yb  閱讀(6849)  評論(2)    收藏  舉報
      主站蜘蛛池模板: 无码里番纯肉h在线网站| 玩弄漂亮少妇高潮白浆| 新版资源天堂中文| 狠狠躁日日躁夜夜躁欧美老妇 | 亚洲国产天堂久久综合226114| 亚洲中文久久久精品无码| 日本免费精品| 亚洲免费一区二区av| 国产精品自拍中文字幕| 奇米777四色影视在线看| 国产成人午夜精品永久免费| 色综合热无码热国产| 亚洲精品日产AⅤ| 肥西县| 国产精品久久久久久久专区| 国产欧美日韩视频怡春院| 高清无码爆乳潮喷在线观看| 亚洲精品一区二区三区蜜臀| 亚洲色大成网站www久久九| 丰满人妻熟妇乱精品视频| 亚洲人成网线在线播放VA| 大石桥市| 漂亮人妻被强中文字幕久久| 一级片免费网站| 少妇爽到呻吟的视频| 亚洲国产超清无码专区| 免费人妻无码不卡中文字幕18禁| 无码乱人伦一区二区亚洲| 天天综合亚洲色在线精品| 邢台市| 久久天天躁夜夜躁狠狠85| 妖精视频yjsp毛片永久| 最新国产AV最新国产在钱| 日韩精品一区二区蜜臀av| 熟女性饥渴一区二区三区| 国产三级国产精品久久成人| 九九热免费精品视频在线| 丰满岳乱妇久久久| 国产精品中文字幕观看| 东京热av无码电影一区二区| 中国老熟妇自拍hd发布|