1. gzyueqian
      13352868059

      武漢粵嵌教你怎么學(xué)習(xí)嵌入式開發(fā)調(diào)試的方法

      更新時間: 2018-10-15 14:27:12來源: 武漢嵌入式培訓(xùn)瀏覽量:5638

          在嵌入式項目的開發(fā)中,受限于資源和工具,對程序的調(diào)試往往沒有PC環(huán)境下的那么容易和輕松。而在嵌入式開發(fā)中,因為設(shè)備和環(huán)境的多樣性、復(fù)雜性更易遇到各種奇怪的問題,這就產(chǎn)生了一個矛盾。為了定位和解決程序的問題,往往需要花費(fèi)很大的精力,這就是近一個禮拜我的經(jīng)歷。排查一個偶然才會出現(xiàn)的段錯誤,也才只是定位到線程棧被改寫的位置,而沒有定位到改寫它的代碼段,所以還是一籌莫展。這里總結(jié)一下用過和可用的調(diào)試方法與經(jīng)驗。
          簡單:printf
          在合理關(guān)鍵的路徑位置添加打印信息是簡單,有時也是有效的方法。如果程序的問題總是在固定的代碼位置復(fù)現(xiàn),那么通過在路徑上添加打印信息就是快速的定位問題出現(xiàn)在哪一代碼行的方法。除了直接使用printf函數(shù)外,可以借鑒日志文件的記錄格式來獲取更多的信息,下面是我自己常用來替代日志記錄的宏封裝,可以指定打印信息的級別以便于分析和篩選:
          宏中的level在使用時直接填寫想要的信息級別就可以,比如常用的:DBG,ERR,WRN等,使用示例:
          實用:日志文件
          printf是輸出到標(biāo)準(zhǔn)輸出或者終端的,需要人為地實時進(jìn)行跟蹤或者保存,否則就會失去這些信息。對于中大型的項目來說,大量地使用printf來進(jìn)行跟蹤和調(diào)試是不現(xiàn)實的,也不可能用眼睛去掃描那不斷刷新的打印屏幕。程序運(yùn)行過程的日志文件記錄是實用規(guī)范的用來跟蹤程序運(yùn)行路徑的方法。
          實現(xiàn)一套日志文件記錄接口沒有什么難度,簡單的只需要將上面宏中的printf改成fprintf就可以,因此在嵌入式開發(fā)中,往往不同的項目常常會實現(xiàn)自己的日志記錄接口。這只是一種輕量的重復(fù)勞動,倒問題不大,除了不利于程序的移植外。此外日志記錄還是有不少細(xì)節(jié)需要考慮的,比如:循環(huán)覆蓋寫、不同線程或進(jìn)程的同步寫等問題,有時實現(xiàn)很容易會疏漏。這里推薦一個用C語言實現(xiàn)開源日志庫:zlog,它提供了線程安全的日志記錄接口和獨立的日志接口行為配置文件,因此在不修改項目代碼的情況下,你可以通過修改外部的zlog日志格式和行為配置文件來改變?nèi)罩居涗浀母袷胶褪欠裼涗浀饺罩疚募小?/span>
      獲取線程ID和名稱
          在多線程的程序中,獲取線程的ID有現(xiàn)成的接口,但是獲取線程的名稱沒有。在Linux2.6及更低版本的linux中,線程是使用clone系統(tǒng)調(diào)用創(chuàng)建進(jìn)程來實現(xiàn)的,此時pthread的線程ID和線程本身的進(jìn)程ID是不一致的。這里提供一個參考的實現(xiàn)來獲取線程ID和名稱:
          關(guān)于gettid參考linux中的man手冊,注意其中的NOTES:
          直接:gdb+gdbserver+core
          在linux上常用的調(diào)試工具就是gdb,它也是給力的調(diào)試?yán)鳌R虼?a href="http://www.jkendeljohnson.com/yqnews" target="_blank">嵌入式開發(fā)中遇到棘手的問題是,首先想到的就是gdb工具。使用gdb進(jìn)行嵌入式程序的調(diào)試有三種途徑:
          交叉編譯gdb
          如果開發(fā)板上的資源(內(nèi)存和flash)充足的話,可以考慮下載gdb的源代碼直接交叉編譯得到可在開發(fā)板上運(yùn)行的gdb工具,然后在編譯嵌入式程序時加-g參數(shù)以保留調(diào)試符號信息,就可以直接在開發(fā)板上進(jìn)行g(shù)db的調(diào)試了。
          gdbserver遠(yuǎn)程調(diào)試
          交叉編譯出的gdb一般會比較大,我這邊使用arm-none-linux-gnueabi工具鏈編出的stripped后的都有3.3M。考慮到資源情況就需要使用gdbserver遠(yuǎn)程調(diào)試的方法,詳細(xì)的步驟參考前文:使用gdbserver遠(yuǎn)程調(diào)試。這里使用時的說明幾個注意點:
          gdb和gdbserver的版本必須是一致的,PC上運(yùn)行的應(yīng)該是編譯工具鏈提供的gdb。
          PC上加載的程序和庫應(yīng)該是debug版本的,即not stripped的,以提供符號和代碼信息。
          PC上使用的庫的版本應(yīng)該和開發(fā)板上使用的庫版本一致,否則會出現(xiàn)庫不匹配的warning。
          PC上使用gdb時首先應(yīng)該設(shè)置好相應(yīng)的環(huán)境變量及信號處理方式,以有效控制程序行為。
          PC上可以通過寫gdb的配置文件來實現(xiàn)環(huán)境和信號處理方式的設(shè)置,使用示例,下面是ak-gdbinit配置文件:
          使用時的命令如下,假設(shè)配置文件在/tftpboot目錄下:
          分析core文件
          像我在項目中遇到的問題:程序運(yùn)行10幾個小時或者幾天后偶爾才出現(xiàn)段錯誤,這讓我使用gdbserver時很郁悶,開著gdb+gdbserver等了兩天都不出現(xiàn)段錯誤,而一不小心把gdb給關(guān)了就前功盡棄了。這種場景就是使用gdb+core文件調(diào)試的選擇了。
          首先你得確定你的問題會不會生成core文件,SIGSEGV信號產(chǎn)生時,linux系統(tǒng)會生成core文件,所以我可以使用這種方法來調(diào)試。參考《APUE》P235可以知道還有以下信號的默認(rèn)動作是終止+core:
          SIGABRT
          SIGBUS
          SIGEMT
          SIGFPE
          SIGILL
          SIGIOT
          SIGQUIT
          SIGSEGV
          SIGSYS
          SIGTRAP
          SIGXCPU
          SIGXFSZ
          然后就是設(shè)置保存core文件的環(huán)境和使用,參考之前的:Linux系統(tǒng)中core文件調(diào)試方法。
          gdb加載core文件時如果出現(xiàn)下面的警告:
          也許只是因為你使用的是帶調(diào)試信息的程序,而開發(fā)板上生成core文件的是stripped后的程序,所以不用擔(dān)心。
          使用gdb調(diào)試時,對于多線程,以下的一些gdb命令是比較有用的:

      免費(fèi)預(yù)約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 日本欧美真人三级在线A | 伊人色综合一区二区三区 | 色妞亚洲欧美精品在线 | 日韩国产欧美一级 | 亚洲国产午夜精品大秀视频 | 亚洲理论在线中文字幕a |