《嵌入式Linux開發(fā)實踐教程 第2版》 課件 項目4 使用嵌入式Linux常用開發(fā)工具_第1頁
《嵌入式Linux開發(fā)實踐教程 第2版》 課件 項目4 使用嵌入式Linux常用開發(fā)工具_第2頁
《嵌入式Linux開發(fā)實踐教程 第2版》 課件 項目4 使用嵌入式Linux常用開發(fā)工具_第3頁
《嵌入式Linux開發(fā)實踐教程 第2版》 課件 項目4 使用嵌入式Linux常用開發(fā)工具_第4頁
《嵌入式Linux開發(fā)實踐教程 第2版》 課件 項目4 使用嵌入式Linux常用開發(fā)工具_第5頁
已閱讀5頁,還剩172頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領

文檔簡介

編譯程序-GCC物聯(lián)網(wǎng)學院平震宇了解GCCGCC原名為GNUC語言編譯器(GNUCCompiler),GCC(GNUCompilerCollection,GNU編譯器套件)Fortran、Pascal、Objective-C、Java、Ada、Go

GCC版本1987年GCC發(fā)布首個公開發(fā)布版本。2012年為了慶祝25周年,GCC發(fā)布了GCC4.7.0版本,這是GCC一個全新的重要版本。

GCC8.2

released

[2018-07-26]GCC8.1

released

[2018-05-02]GCC7.3

released

[2018-01-25]GCC5.5

released

[2017-10-0]GCC7.2

released

[2017-08-14]GCC6.4

released

[2017-07-04]GNUBinutilsGNUBinutils,即GNUBinaryUtilities的簡寫,一般簡稱為Binutils。GNUBinutils,中文可以翻譯為GNU的二進制工具集。GNUBinutils,是一組二進制工具的集合。

GNUBinutils中包含的主要工具ld鏈接器

將多個目標文件,鏈接成一個可執(zhí)行文件(或目標庫文件)。as匯編器

將匯編源代碼,編譯為(目標)機器代碼

GNUBinutils中包含的其他次要工具addr2line

將地址轉(zhuǎn)換為(文件名和)行號的工具,以便于調(diào)試ar

用來操作(.a)文件,比如創(chuàng)建,修改,提取內(nèi)容等.c++filt

由于每一個重載的函數(shù)都使用與原函數(shù)相同的名稱,因此,支持函數(shù)重載的語言必須擁有一種機制,以區(qū)分同一個函數(shù)的許多重載版本。c++filt將每個輸入的名稱看成是改編后的名稱(mangledname),并設法確定用于生成該名稱的編譯器。dlltool

基于obj文件(基中函數(shù)標記為__declspec(dllexport))或def文件生成exp和lib文件。前者(exp文件,其中包含了.edata段)是用于創(chuàng)建dll,后者(lib文件,包含.idata段)用于使用dll。

GNUBinutils中包含的其他次要工具gold

一個新的,速度更快的,只針對于ELF的鏈接器gprof

打印出程序運行中各個函數(shù)消耗的時間,可以幫助程序員找出眾多函數(shù)中耗時最多的函數(shù)。nm

列舉目標文件中的符號以及與符號有關(guān)的一些信息。Objcopy

把目標文件的內(nèi)容從一種文件格式復制到另一種格式的目標文件中。Objdump

顯示目標文件信息,可以反編譯二進制文件,也可以對對象文件進行反匯編,并查看機器代碼。

GNUBinutils中包含的其他次要工具ranlib

生成索引以加快對歸檔文件的訪問,并將結(jié)果保存到這個歸檔文件中readelf

顯示符號、段信息、二進制文件格式的信息等,這在分析編譯器如何工從源代碼創(chuàng)建二進制文件時非常有用。size

可以列出目標文件或者一個歸檔文件每一段的大小以及總體的大小strings

用于提取文件中的字符串內(nèi)容,使用該工具不會受到文件格式的限制。

strip

去除符號,比如用于debug的信息,在不影響程序功能的前提下,減少可執(zhí)行文件的大小,減少程序的占用空間

任務要求StepOne安裝GCC編譯器StepTwoGCC的編譯過程StepThreeGCC編譯實例StepOne安裝GCC通過GCC–v查看當前的GCC版本gcc-v解壓gcc源碼包tarxzvfgcc-4.7.4.tar.gzStepOneinstallgmp./configure--prefix=/opt/gmp-4.3.2installmpfr./configure--prefix=/opt/mpfr-2.4.2--with-gmp=/opt/gmp-4.3.2installmpcStepOne配置../gcc-4.7.4/configure--prefix=/opt/gcc-4.7--with-gmp=/opt/gmp-4.3.2--with-mpfr=/opt/mpfr-2.4.2--with-mpc=/opt/mpc-1.0.1--enable-languages=c,c++,java編譯安裝makemakeinstallStep2程序的編譯過程

.C預處理.s.i編譯.o匯編hex鏈接預處理階段gcc–Ehello.c–ohello.iStep2程序的編譯過程

.C預處理.s.i編譯.o匯編.o鏈接編譯階段gcc–S

hello.i–ohello.sStep2程序的編譯過程

.C預處理.s.i編譯.o匯編.o鏈接匯編階段gcc–chello.s–ohello.oStep2程序的編譯過程

.C預處理.s.i編譯.o匯編.o鏈接鏈接階段gcchello.o–ohelloStep3

GCC編譯實例編譯簡單的C程序gcc-g-Wallhello.c–ohello選項""-g""表示在生成的目標文件中帶調(diào)試信息選項-Wall開啟編譯器幾乎所有常用的警告warning:前面是懸崖,不要再往前走了。-w

:關(guān)閉所有警告-Wall:開啟所有錯誤提示-Werror:把警告當作錯誤來處理警告選項-gformat:指定要生成的調(diào)試信息的格式以提供給其他平臺的其他調(diào)試器使用-g:以操作系統(tǒng)的本地格式(stabs,COFF,XCOFF,或DWARF)產(chǎn)生調(diào)試信息-pg:產(chǎn)生額外代碼用于輸出profile信息,供分析程序gprof使用調(diào)試選項

#include<head.h>#include“myhead.h”gcc-vhello.c-I/home/test-I

dir在頭文件的搜索路徑列表中添加dir目錄頭文件的處理鏈接庫的處理CompilerC源文件Olib目標文件Linkerhex可執(zhí)行文件靜態(tài)庫動態(tài)庫libc.so#標準C庫,動態(tài)鏈接庫libpthread.a#線程庫,靜態(tài)鏈接庫一個特殊靜態(tài)鏈接庫方式,把庫完整名字加入gcc-ohellohello.olibmy.a-l參數(shù)用來鏈接庫標準表達式方式-lpthread表示鏈接libpthread.sogcchello.c-lpthread-ohello-L參數(shù)來指明從哪一個目錄加載庫在/home/test/lib/目錄下有鏈接時所需要的庫文件libmy.so

gcchello.c-L/home/test/lib-lmy–ohello新安裝一個庫之后如何讓系統(tǒng)能夠找到呢?1.編輯/etc/ld.so.conf文件,加入庫文件所在目錄的路徑2.運行l(wèi)dconfig,該命令會重建/etc/ld.so.cache文件代碼優(yōu)化優(yōu)化級別1(-O1)優(yōu)化級別2(-O2)優(yōu)化級別3(-O3)StepThree編譯多個源文件gcc-Wallcalc.ccalc_fn.c-onewcalc

GCC編譯實例調(diào)試程序-GDB物聯(lián)網(wǎng)學院平震宇了解GDBGDB是一個強大的命令行調(diào)試工具。UNⅨ下的軟件全是命令行的,這給程序開發(fā)提代供了極大的便利,命令行軟件的優(yōu)勢在于,它們可以非常容易的集成在一起,使用幾個簡單的已有工具的命令,就可以做出一個非常強大的功能。

UNⅨ下的軟件比Windows下的軟件更能有機地結(jié)合,各自發(fā)揮各自的長處,組合成更為強勁的功能。Windows下的圖形軟件基本上是各自為營,互相不能調(diào)用,很不利于各種軟件的相互集成?!按缬兴L,尺有所短”,圖形化工具還有時不如命令行的地方。

GDB功能啟動你的程序,可以按照你的自定義的要求隨心所欲的運行程序??勺尡徽{(diào)試的程序在你所指定的調(diào)置的斷點處停住。(斷點可以是條件表達式)當程序被停住時,可以檢查此時你的程序中所發(fā)生的事。你可以改變你的程序,將一個BUG產(chǎn)生的影響修正從而測試其他BUG。

GNUDebuggerGNUDebugger最初是在1988年由理查德·馬修·斯托曼(RichardStallman,自由軟件的精神領袖)所撰寫,之后以GNU通用公共許可證的授權(quán)方式將軟件發(fā)布。

任務要求Step1熟悉使用GDB調(diào)試程序的流程Step2熟悉GDB常用命令Step3GDBServer遠程調(diào)試GDB常用命令任務要求Step1查看源程序Step2暫停/恢復程序運行Step3查看運行時數(shù)據(jù)StepOne安裝GDB通過GDB–v查看當前的GDB版本gdb-v解壓gcc源碼包tarxzvfgdb-7.4.tar.gzStepTwo如何單步執(zhí)行?如何打印變量的值?(printvar)

如何打印變量的地址?(print&var)

如何打印地址的數(shù)據(jù)值?(print*address)

如何查看當前運行的文件和行?(backtrace)

如何查看指定文件的代碼?(listfile:N)

如何立即執(zhí)行完當前的函數(shù),但是并不是執(zhí)行完整個應用程序?(finish)

如果程序是多文件的,怎樣定位到指定文件的指定行或者函數(shù)?(listfile:N)

如果循環(huán)次數(shù)很多,如何執(zhí)行完當前的循環(huán)?(until)

GNUGCC開發(fā)教程gnugccturiolgnugcc簡介目前Linux下最常用的C語言編譯器是GCC(GNUCompilerCollection),它是GNU項目中符合ANSIC標準的編譯系統(tǒng).是Linux的基石,操作系統(tǒng)內(nèi)核和大部分程序都是gcc編譯的,是Linux下最重要開發(fā)工具之一gcc早期是c的編譯器,后來發(fā)展能支持c,c++和objectC,它可以通過不同的前端模塊來支持各種語言,如Java、Fortran、Pascal、Modula-3和Ada等。

gcc是一個交叉平臺的編譯器,目前支持幾乎所有主流CPU的處理器平臺.gcc支持的文件格式gcc支持源碼格式.c C源程序;.C,.cc,.cxx,.cpp C++源程序;.m Objective-C源程序;.i 預處理后的C文件;.ii 預處理后的C++文件;.s 匯編語言源程序;.S 匯編語言源程序;.h 預處理器文件;其它格式.o目標文件(Objectfile).a歸檔庫文件(Archivefile)GCC組成gcc一般安裝在/usr/bingcc是一組編譯工具的總稱,包含如下工作C編譯器cc,cc1,cc1plus,gccC++編譯器c++,cc1plus,g++源碼預處理程序cpp,cpp0庫文件libgcc.a,libgcc_eh.a,libgcc_s.so,ibiberty.a,libstdc++,libsupc++.agcc的起步生成一個hello,world程序gcchello.c-ohello#把hello.c編譯成一個可執(zhí)行程序hellogcchello.c#不指定輸出名,生成一個a.outHello程序#include<stdio.h>#defineMY_NUMBER5intmain(void){printf("Hello%d,theWorld!\n",MY_NUMBER);return0;}編譯hello用GCC編譯程序可執(zhí)行程序的構(gòu)造任何一個可執(zhí)行程序從源代碼到可執(zhí)行的二進制程序之中都要經(jīng)過固定的幾步預編譯(Pre-Processing)這一步完成對預編譯代碼的處理編譯(Compiling)將源代碼編譯成匯編代碼匯編(Assembling)將匯編代碼匯編成目標文件鏈接(Linking)將目標代碼和所需要庫的鏈成一個完整的應用程序集成開發(fā)環(huán)境(IDE)自動協(xié)助開發(fā)完成這幾步,如VC++在Linux下,如果使用命令行開發(fā)工具(gcc,ld,ar)等,需要用戶手工調(diào)用這一些命令來完成這幾步驟.gcc在構(gòu)建程序的作用gcc在構(gòu)建應用程序里,會調(diào)用不同的應用程序完成每一步.因此在開發(fā)中,gcc處于一個核心地位.大部分開發(fā)只需要調(diào)用gcc即可gcc所做操作Gcc調(diào)用cpp進行預處理Gcc調(diào)用cc1進行編譯,會生成匯編代碼Gcc調(diào)用as對匯編代碼,生成擴展名為.o的目標文件Gcc調(diào)用ld來完成對所有目標文件的鏈接.為什么要用gcc隨著Linux的GUI改進,也出現(xiàn)了越來越多的IDE開發(fā)環(huán)境.象VC++,自動完成各個開發(fā)流程但這一些IDE基本上是基于gcc編譯而且大部分項目,包括嵌入式開發(fā),都是提供gcc命令行開發(fā)模式.因此用gcc開發(fā)是Linux和嵌入式開發(fā)的必須使用的工具.也是基本功之一hello編譯過程分析以下將上述gcc編譯過程,分成幾個步驟單獨進行,并生成每步運行結(jié)果供觀察第一步是進行預編譯,使用-E參數(shù)可以讓GCC在預處理結(jié)束后停止編譯過程:#

gcc-Ehello.c-ohello.i下一步是將hello.i編譯為目標代碼,這可以通過使用-c參數(shù)來完成,。#

gcc-chello.i-ohello.o最后一步是將生成的目標文件鏈接成可執(zhí)行文件#

gcchello.o-ohello注意:gcc編譯時是對輸入文件擴展名是敏感的,即.c一定會當做C代碼編譯,.cpp,.C…一定會當成C++代碼編譯,這一點跟大部分Linux程序不一樣gcc的結(jié)果輸出是后綴名不相關(guān)的.只與輸出參數(shù)相關(guān).這跟一般Linux程序是一樣gcchello.c-ohello.o#雖然后綴名是.o,但實際是一個應用程序gcc各個編譯步驟多文件gcc的處理在采用模塊化的設計思想進行軟件開發(fā)時,通常整個程序是由多個源文件組成的,相應地也就形成了多個編譯單元,使用GCC能夠很好地管理這些編譯單元。假設有一個由foo1.c和foo2.c兩個源文件組成的程序,為了對它們進行編譯,并最終生成可執(zhí)行程序foo,可以使用下面這條命令:gccfoo1.cfoo2.c-ofoo在編譯一個包含許多源文件的工程時,若只用一條GCC命令來完成編譯是非常浪費時間的。假設項目中有100個源文件需要編譯,并且每個源文件中都包含10000行代碼,如果像上面那樣僅用一條GCC命令來完成編譯工作,那么GCC需要將每個源文件都重新編譯一遍,然后再全部連接起來。很顯然,這樣浪費的時間相當多,尤其是當用戶只是修改了其中某一個文件的時候,完全沒有必要將每個文件都重新編譯一遍,因為很多已經(jīng)生成的目標文件是不會改變的。要解決這個問題,關(guān)鍵是要靈活運用GCC,同時還要借助像Make這樣的工具。用gcc構(gòu)造程序(1)在只有一個源代碼文件構(gòu)造出來的可執(zhí)行程序.只需要用到如下形式gcchello.c-ohello表示將hello.c一次做完四步,構(gòu)造出可執(zhí)行程序hello,gcchello.c將hello.c構(gòu)造一個可執(zhí)行程序,有缺省名a.out,但不建議這樣做.gcc-chello.c-ohello這一步驟是初學者常犯錯誤.以為等于在一次性構(gòu)造應用程序hello但實際上這只是在編譯c并生成一個目標文件hello,即便是沒有.o的后綴.這個用file命令可以很容易查看,這個hello是無法執(zhí)行.用gcc構(gòu)造程序(2)使用多個源碼的項目,如項目中包含2個以上的源代碼,一般要先將源代碼編譯成目標代碼.最后一次鏈接成可執(zhí)行程序以鏈表測試程序為例.整個項目由兩個c代碼(test_link.c和link_list.c)和一個頭文件(link_list.h)組成.頭文件是包含在源代碼里,由預處理程序處理,不需要編譯首先各自己編譯成目標文件gcc-clink_list.c#將link_list.c編譯成link_list.ogcc-ctest_link.c#將test_link.c編譯成test_link.o然后將各個目標文件鏈接成一個文件gcclink_list.otest_link.o-otest_link#生成可執(zhí)行文件test_link也可以直接把兩個文件在一句里編譯,但強烈建議不要這樣做gcclink_list.ctest_link.c-otest_link編譯test_link實例用gcc構(gòu)造程序(3)gcc的對絕大部分參數(shù)順序一般沒有要求,但為可讀性強,最好要按一定順序執(zhí)行g(shù)cclink_list.o-otest_link.otest_link等效于gcclink_list.otest_link.o-otest_link,但前者可讀性差很多.但多個-l(鏈接)參數(shù)的順序是有要求的對于有頭文件在多個目錄時,需要在編譯時多次使用用-I參數(shù)加入頭文件所在目錄.例如test_link.c需要用到/usr/include,當前目錄下,/home/hxy目錄下的頭文件.則如下編譯gcc-I.-I/usr/include-I/home/hxy-ctest_link.cgcc構(gòu)造復雜程序一個大型項目,一個可執(zhí)行程序可能擁有多個位于不同目錄的頭文件,多個源碼文件,還可能鏈接一些靜態(tài)庫或動態(tài)庫,這一些都需要用到gcc的一些擴展選項.gcc的參數(shù)參見下一節(jié)可能調(diào)用gcc很多次,如果完全手工編寫,將是一個浩大的工程需要寫一個類似Shell腳本的Makefile來調(diào)用gcc構(gòu)造GCC選項gcc完整使用格式gcc使用格式

gcc[option|filename]...g++[option|filename]...

其中option為gcc使用時的選項(后面會再詳),

而filename為欲以gcc處理的文件

總體選項(OverallOption)-c-S-E-ofile-pipe-v-xlanguagegcc選項(1)-xlanguage明確指出后面輸入文件的語言為language(而不是從文件名后綴得到的默認選擇).這個選項應用于后面所有的輸入文件,直到遇著下一個`-x'選項.language的可選值有`c',`objective-c',`c-header',`c++',`cpp-output',`assembler',和`assembler-with-cpp'.gcc-xc++hello.c強制用c++來編譯-xnone關(guān)閉任何對語種的明確說明,因此依據(jù)文件名后綴處理后面的文件(就象是從未使用過`-x'選項).gcc選項(2)-c編譯或匯編源文件,但是不作連接.編譯器輸出對應于源文件的目標文件.缺省情況下,GCC通過用`.o'替換源文件名后綴`.c',`.i',`.s',等等,產(chǎn)生目標文件名.可以使用-o選項選擇其他名字.GCC忽略-c選項后面任何無法識別的輸入文件(他們不需要編譯或匯編).gcc–chello.cgcc選項(3)-S編譯后即停止,不進行匯編.對于每個輸入的非匯編語言文件,輸出文件是匯編語言文件.缺省情況下,GCC通過用`.o'替換源文件名后綴`.c',`.i',等等,產(chǎn)生目標文件名.可以使用-o選項選擇其他名字.GCC忽略任何不需要編譯的輸入文件.相當于編譯源碼,只生匯編代碼

gcc–Shello.c–ohello.sgcc選項(4)-E預處理后即停止,不進行編譯.預處理后的代碼送往標準輸出.GCC忽略任何不需要預處理的輸入文件gcc–Ehello.c–ohello.i-v(在標準錯誤)顯示執(zhí)行編譯階段的命令.同時顯示編譯器驅(qū)動程序,預處理器,編譯器的版本號.gcc-vgcc選項(5)-ofile指定輸出文件為file.該選項不在乎GCC產(chǎn)生什么輸出,無論是可執(zhí)行文件,目標文件,匯編文件還是預處理后的C代碼.由編譯階段決定,輸入的格式gcc-Ehello.c-ohello.igcc-chello.i-ohello.ogcchello.c–ohello只能輸出一個文件gcc選項(6)-pipe在編譯過程的不同階段間使用管道而非臨時文件進行通信.在將源代碼變成可執(zhí)行文件的過程中,需要經(jīng)過許多中間步驟,包含預處理、編譯、匯編和連接。這些過程實際上是由不同的程序負責完成的。大多數(shù)情況下GCC可以為Linux程序員完成所有的后臺工作,自動調(diào)用相應程序進行處理。是GCC在處理每一個源文件時,最終都需要生成好幾個臨時文件才能完成相應的工作,從而無形中導致處理速度變慢。例如,GCC在處理一個源文件時,可能需要一個臨時文件來保存預處理的輸出、一個臨時文件來保存編譯器的輸出、一個臨時文件來保存匯編器的輸出,而讀寫這些臨時文件顯然需要耗費一定的時間。當軟件項目變得非常龐大的時候,花費在這上面的代價可能會變得很沉重。解決的辦法是,使用Linux提供的一種更加高效的通信方式—管道。它可以用來同時連接兩個程序,其中一個程序的輸出將被直接作為另一個程序的輸入,這樣就可以避免使用臨時文件,但編譯時卻需要消耗更多的內(nèi)存。gcc-pipefoo.c-ofoo

關(guān)于宏(macro)的選項-Dmacro定義宏macro,宏的內(nèi)容定義為字符串`1'.gcctest_m.c–D__DEBUG–otest_m-Dmacro=defn定義宏macro的內(nèi)容為defn.命令行上所有的`-D'選項在`-U'選項之前處理.gcctest_m.c–D__DBG_NAME=hello–otest_m-Umacro取消宏macro.`-U'選項在所有的`-D'選項之后處理,但是優(yōu)先于任何`-include'gcc警告提示功能

GCC包含完整的出錯檢查和警告提示功能,它們可以幫助Linux程序員寫出更加專業(yè)和優(yōu)美的代碼。編譯警告代碼-pedantic打開完全服從ANSIC標準所需的全部警告診斷,如里出現(xiàn)非標準擴展,則拒絕編譯,所以叫書呆子pedant.-ansi支持符合ANSI標準的C程序.這樣就會關(guān)閉GNUC中某些不兼容ANSIC的特性,例如asm,inline和typeof關(guān)鍵字,以及諸如unix和vax這些表明當前系統(tǒng)類型的預定義宏.同時開啟不受歡迎和極少使用的ANSItrigraph特性,以及禁止`$'成為標識符的一部分.與pedantic區(qū)別在于,只是警告,如果需要停止編譯,仍然需要打開-pedanticgcc警告提示功能(2)-Wall打開所有編譯警告gcc-Wallillcode.c-oillcode-Werror視警告為錯誤;出現(xiàn)任何警告即放棄編譯.gcc-Wall-Werrorillcode.c-oillcode-w禁止輸出警告信息調(diào)試分析選項-g以操作系統(tǒng)的本地格式(stabs,COFF,XCOFF,或DWARF).產(chǎn)生調(diào)試信息.GDB能夠使用這些調(diào)試信息,是進行g(shù)db調(diào)試必備條件和大多數(shù)C編譯器不同,GNUCC允許結(jié)合使用`-g‘和`-O’選項,但一般不建議一起使用gcchello.c-g-ohello-pg產(chǎn)生額外代碼,用于輸出profile信息,供分析程序gprof使用.所有調(diào)試選項會使用最終輸出文件尺寸急劇增加,在最后發(fā)布,需要使用strip命令把調(diào)試信息去掉,striphellogcc使用庫使用第三方庫在Linux下開發(fā)軟件時,完全不使用第三方函數(shù)庫的情況是比較少見的,通常來講都需要借助一個或多個函數(shù)庫的支持才能夠完成相應的功能。從程序員的角度看,函數(shù)庫實際上就是一些頭文件(.h)和庫文件(.so或者.a)的集合。雖然Linux下的大多數(shù)函數(shù)都默認將頭文件放到/usr/include/目錄下,而庫文件則放到/usr/lib/目錄下,但并不是所有的情況都是這樣。正因如此,GCC在編譯時必須有自己的辦法來查找所需要的頭文件和庫文件。GCC采用搜索目錄的辦法來查找所需要的文件,-I選項可以向GCC的頭文件搜索路徑中添加新的目錄。例如,如果在/home/hxy/upgrade/include/目錄下有編譯時所需要的頭文件,為了讓GCC能夠順利地找到它們,就可以使用-I選項:gccfoo.c-I/home/xiaowp/include-ofoo在一個gcc命令中可以用多個-I兩大類庫形式C/C++可以使用兩種庫.一種是靜態(tài)庫,另外一種是動態(tài)庫.靜態(tài)庫在鏈接時會把庫目標代碼與最終的可執(zhí)行程序一起鏈接到一個文件,這樣相對尺寸較大.但處理簡單.而動態(tài)庫是可執(zhí)行程序在運行,動態(tài)加載到進程內(nèi)存中去.動態(tài)庫與可執(zhí)行程序是分離的兩部分文件.兩者在作用是完全等效,主要是使用方法不同.由開發(fā)者根據(jù)項目情況自行評估使用哪種形式.Windows下的靜態(tài)庫是以lib為后綴名的文件,而動態(tài)庫是以DLL為后綴名的文件.Linux下的動態(tài)鏈接庫是so為后綴,和靜態(tài)鏈接庫以.a為后綴名Linux的庫的命名Linux庫的命名有一個特殊的要求,即要是lib打頭,以.so或a結(jié)尾libc.so#標準C庫,動態(tài)鏈接庫libpthread.a#線程庫,的靜態(tài)鏈接庫版本.在一般使用時,為防止不同版本庫互相覆蓋,一般還在系統(tǒng)庫名后加入版本號.libm.so.6#math庫ver6.0版本Libc-2.3.2.so#標準Cver2.3.2動態(tài)庫但為方便gcc使用,通常都對這一些帶版本名的庫作一個符號鏈接,鏈接名則是標準形式,如libc.so.Linux一般把系統(tǒng)庫放在/lib下.這是大部分庫命名的習慣,也可以不遵守,如果強行做一個叫mystd.a的庫,但使用起來很不方便,如不能使用-l參數(shù)等,所以建議不要這樣做.gcc鏈接庫gcc是在鏈接時,把庫加入可以程序中.一個特殊靜態(tài)鏈接庫方式.把庫完整名字加入gcc-ohellohello.olibmy.a鏈接hello.o,和庫libmy.a到某一個程序hello中g(shù)cc-ohellohello.olibmy.so鏈接hello.o,和庫libmy.so到某一個程序hello中,注意這里沒有直接把libmy.so代碼加入hello中這一方法主要用于鏈接不標準庫名稱,或混和鏈接(即一部分庫用于靜態(tài)版本,一部分庫用動態(tài)版本).但不是正規(guī)用法,強烈建議不要使用這一方法gcc-l參數(shù)的使用gcc-l參數(shù)用來鏈接庫標準表達式方式.-l接的庫名,是去掉lib和后綴名(.so,.a)剩下的部分,gccfoo.c-lpthread-ofoo構(gòu)造foo,鏈接庫pthread.-lpthread表示鏈接libpthread.so由于去掉后綴名,gcc-l如何知道鏈接是動態(tài)庫還是靜態(tài)庫?,gcc有如下規(guī)則:如果gcc所能找到庫目錄同時有兩種版本,優(yōu)先鏈接動態(tài)鏈接庫版本如果gcc所能找到庫目錄只有靜態(tài)版本,則采用靜態(tài)版本如果加上-static參數(shù),gcc則強制鏈接靜態(tài)版本gccfoo.c-static-lpthread-ofoo-lpthread表示鏈接libpthread.a一個使用線程庫的例子gcc-L參數(shù)的使用gcc所編譯的目標文件和庫通常不是在同一個目錄下.因此必須強制指明gcc要從哪一個目錄加載庫gcc在鏈接時采用-L參數(shù)來指明從哪一個目錄加載庫例如,如果在/home/hxy/lib/目錄下有鏈接時所需要的庫文件libfoo.sogccfoo.c-L/home/hxy/lib-lfoo-ofoo一個gcc語句可以包含多個-L參數(shù)在編譯時目標文件時使用-L無效標準庫,gcc能自行找到,無需使用-L參數(shù)在一些應用中,鏈接多個庫是有順序的,大部分無所謂如在系統(tǒng)中l(wèi)iba.a使用libpthread.a中的函數(shù),而可執(zhí)行程序同時使用兩個庫,則使用者liba.a的鏈接語句放在被使用者libpthread.a的前面,gccfoo.c-L/home/hxy/lib–la-lpthread-ofoo只是為了保險.在BerkeleyDB中就出現(xiàn)這種情況,pthread在前,則所有線程庫的函數(shù)找不到gcc-I參數(shù)的使用庫的頭文件通常也跟源文件不在同一個目錄之下,為了讓gcc找到頭文件,可以-I<頭文件目錄>來加入頭目錄.gcc是在編譯時使用-I,在鏈接時無效.這跟-L參數(shù)剛好相反一個gcc語句中可以使用多個-Igcc創(chuàng)建庫關(guān)于庫的演示代碼在隨后的演示中,將采用如下演示代碼.Strlen.c,Strnlen.c分別實現(xiàn)了兩個自定義示字符串長度函數(shù)這兩個函數(shù)的聲明在String.h中main.c分別用靜態(tài)鏈接,隱式動態(tài)鏈接來測試使用了Strlen.c,Strnlen.c的函數(shù),并使用.main_dl.c用顯示動態(tài)鏈接來調(diào)用庫代碼在隨后的例子里把Strlen.c,Strnlen.c分別編譯成靜態(tài)庫.libstr.a,隱式動態(tài)庫libstr.so,顯示動態(tài)庫libstrdl.so,庫名中最好不用出現(xiàn)大寫字母,gcc是按小寫字母來查找的關(guān)于靜態(tài)鏈接庫在LINUX下,靜態(tài)函數(shù)庫是以.a作后綴的,類似于Windows的lib在鏈接后,靜態(tài)庫的函數(shù)都會鏈接到最終的可執(zhí)行程序里.這樣可執(zhí)行程序的尺寸比動態(tài)鏈接要大.靜態(tài)鏈接的好處是不需要外部文件的支持,獨立運行.在嵌入式環(huán)境下,如果尺寸影響不大,最好用靜態(tài)編譯.創(chuàng)建靜態(tài)鏈接庫gcc不能直接創(chuàng)建靜態(tài)庫.必須要用歸檔命令ar來創(chuàng)建ar用于建立、修改、提取檔案文件(archive)。archive是一個包含多個被包含文件的單一文件(也稱之為庫文件),其結(jié)構(gòu)保證了可以從中檢索并得到原始的被包含文件(稱之為archive中的member)。ar可以把任何文件歸在一起,但通常是用來把gcc編譯的目標文件(.o),合在一個靜態(tài)庫中靜態(tài)庫創(chuàng)建$gcc-Wall-cfile1.cfile2.cfile3.c#一次性編譯三個.o$arrvlibNAME.afile1.ofile2.ofile3.o#把三個o合在一起ar參數(shù){dmpqrtx}中的操作選項在命令中只能并且必須使用其中一個,它們的含義如下:d:從庫中刪除模塊。按模塊原來的文件名指定要刪除的模塊。如果使用了任選項v則列出被刪除的每個模塊。m:該操作是在一個庫中移動成員。當庫中如果有若干模塊有相同的符號定義(如函數(shù)定義),則成員的位置順序很重要。如果沒有指定任選項,任何指定的成員將移到庫的最后。也可以使用'a','b',或'I'任選項移動到指定的位置。p:顯示庫中指定的成員到標準輸出。如果指定任選項v,則在輸出成員的內(nèi)容前,將顯示成員的名字。如果沒有指定成員的名字,所有庫中的文件將顯示出來。q:快速追加。增加新模塊到庫的結(jié)尾處。并不檢查是否需要替換。'a','b',或'I'任選項對此操作沒有影響,模塊總是追加的庫的結(jié)尾處。如果使用了任選項v則列出每個模塊。這時,庫的符號表沒有更新,可以用'ars'或ranlib來更新庫的符號表索引。ar參數(shù)(2)r:在庫中插入模塊(替換)。當插入的模塊名已經(jīng)在庫中存在,則替換同名的模塊。如果若干模塊中有一個模塊在庫中不存在,ar顯示一個錯誤消息,并不替換其他同名模塊。默認的情況下,新的成員增加在庫的結(jié)尾處,可以使用其他任選項來改變增加的位置。

t:顯示庫的模塊表清單。一般只顯示模塊名。x:從庫中提取一個成員。如果不指定要提取的模塊,則提取庫中所有的模塊。但實際最多參數(shù)只有arrv....Replace+verbosearrcv....Replace+Create+verbose創(chuàng)建一個靜態(tài)庫的腳本gcc-cStrlen.cgcc-cStrnlen.c#把兩個目標文件裝入靜態(tài)庫libstr.a中arrv

libstr.aStrlen.oStrnlen.ogcc-cmain.c-I.#鏈接main_a時,一并鏈接libstr.a#gccmain.olibmy.a-omain_a#非標準用法,用全名gccmain.o-L.-lstr-omain_a#標準用法動態(tài)鏈接庫的創(chuàng)建動態(tài)鏈接庫的創(chuàng)建分為兩步:1.編譯目標文件,必須帶上-fpic標志,使輸出的對象模塊是按照可重定位地址方式生成的gcc-cStrlen.c-fpic

gcc-cStrnlen.c-fpic

2.將加入動態(tài)庫的目標文件合并在一起,必須帶上-shared,明確表示是動態(tài)鏈接庫gcc-sharedStrlen.oStrnlen.o-olibstr.so兩步可以合并成一步,但一般不建議這樣做gcc-fpic

-sharedStrlen.cStrnlen.c-olibstr.soso是SharedObject的縮寫動態(tài)鏈接庫的創(chuàng)建#gcc-fpic-sharedStrlen.cStrnlen.c-olibstr.sogcc-c-fpicStrlen.cgcc-c-fpicStrnlen.c#生成動態(tài)鏈接庫gcc-sharedStrlen.oStrnlen.o-olibstr.so#編譯測試程序gcc-cmain.c-I.#鏈接主程序和動態(tài)庫#gccmain.olibstr.so-omain_so#非標準鏈接方式gccmain.o-L.-lstr-omain_so運行中使用動態(tài)鏈接庫一個使用動態(tài)鏈接庫的程序運行時,要做一下設置.否則應用程序會報找不到動態(tài)庫的錯誤隱式調(diào)用和顯式調(diào)用兩種調(diào)用方法.隱式調(diào)用是不采用特殊系統(tǒng)調(diào)用,只是在gcc鏈接采用-l,-L鏈接.這樣代碼影響不大顯式調(diào)用是在運行時,使用動態(tài)庫的文件名來加載,具有靈活的特點,缺點就是必須使用特定的,不可移植的系統(tǒng)調(diào)用來編寫.過程比較復雜一個程序運行后,可以用命令ldd來檢查它使用了哪一些動態(tài)庫ldd./hello隱式調(diào)用動態(tài)方法必須要能讓程序運行能找動態(tài)鏈接庫,Linux有如下幾種方法.把庫所在路徑加入/etc/ld.so.conf,程序加載是會首先到這里路徑查找設置環(huán)境變量LD_LIBRARY_PATH,把庫所在路徑加入這個變量中,這是最常用的方法演示代碼將采用這一方法運行,寫一個腳本run_so.sh將exportLD_LIBRARY_PATH和執(zhí)行語句寫在一行命令中,并用;隔開exportLD_LIBRARY_PATH=$PWD;./mani_so#!/bin/shexportLD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH./main_soldd./main_so#用ldd查看用了哪些動態(tài)庫隱式動態(tài)庫的執(zhí)行結(jié)果動態(tài)庫的顯示調(diào)用顯示調(diào)用,Linux提供4個庫函數(shù)(dlopen,dlerror,dlsym和dlclose),一個include文件(dlfcn.h)以支持動態(tài)鏈接裝入器dlopen

將共享目標文件打開并且映射到內(nèi)存中,并且返回句柄dlsym返回一個指向被請求入口點的指針dlerror

返回NULL或者一個指向描述最近錯誤的ASCII字符串的指針dlclose關(guān)閉句柄并且取消共享目標文件的映射這四個函數(shù)被包含在libdl.a/libdl.so之中,所以使用動態(tài)顯示調(diào)用,必須要鏈接-ldl這一機制是后來加入,模仿Windows下的LoadLibrary/FreeLibrary機制不同調(diào)用方式對動態(tài)庫本身沒有任何影響,需要調(diào)整是調(diào)用庫函數(shù)的應用程序,要做較大調(diào)整.dlopen()的說明void*dlopen(constchar*filename,intflag);將共享目標文件打開并且映射到內(nèi)存中,并且返回句柄聲明在頭文件dlfcn.h之中第一個參數(shù):指定共享庫的名稱,將會在下面位置查找指定的共享庫。dlopencall中的絕對文件路徑在LD_LIBRARY_PATH環(huán)境變量中指定的目錄中在/etc/ld.so.cache中指定的庫列表之中先在/usr/lib之中,然后在/lib之中第二個參數(shù):指定如何打開共享庫。RTLD_NOW:將共享庫中的所有函數(shù)加載到內(nèi)存RTLD_LAZY:會推后共享庫中的函數(shù)的加載操作,直到調(diào)用dlsym()時方加載某函數(shù)

其它dl函數(shù)聲明constchar*dlerror(void);如果上一步的dl函數(shù)出錯,則返回非空字符串,指明錯誤原因

void*dlsym(void*handle,char*symbol);用庫函數(shù)名字symbol在dlopen打開的handle查找一個函數(shù)指針,如果找到,則放入返回值中,應用程序可以直接用函數(shù)指針來操作.intdlclose(void*handle);關(guān)閉dlopen打開的句柄關(guān)于使用顯示動態(tài)庫的步驟必須包含頭文件#include<dlfcn.h>聲明使用的到庫函數(shù)的函數(shù)指針用dlopen打開共享庫用dlsym取得對應庫函數(shù)的函數(shù)指針如果成功,使用直接調(diào)用這個指針.相當于使用庫函數(shù)用完共享庫后,用dlclose釋放共享庫使用顯示調(diào)用實例(1)#include<stdio.h>#include<dlfcn.h>/*

加入頭文件支持*/intmain(intargc,char*argv[]){//definefunctionpointorint(*pStrlenFun)(char*pStr);//聲明對應的函數(shù)的函數(shù)指針

int(*pStrnlenFun)(char*pStr,intulMaxLen);charstr[]={"helloworld"};unsignedlongulLength=0;void*pdlHandle;char*pszErr;

pdlHandle=dlopen(“./libstrdl.so”,RTLD_LAZY);//加載動態(tài)鏈接庫/libstrdl.soif(!pdlHandle){printf("Failedloadlibrary\n");}使用顯示調(diào)用實例(2)/*接上一段代碼*//*判斷dlopen是否打開出錯,如是,打印錯誤后退出*/pszErr=dlerror();

if(pszErr!=NULL){printf("%s\n",pszErr);return0;}//從庫中查找?guī)旌瘮?shù)Strlen的函數(shù)指針

pStrlenFun=dlsym(pdlHandle,"Strlen");//獲取函數(shù)的地址

pszErr=dlerror();if(pszErr!=NULL){printf("%s\n",pszErr);return0;}使用顯示調(diào)用實例(3)/*接上一段代碼*//*從庫中查找?guī)旌瘮?shù)Strnlen的函數(shù)指針*/pStrnlenFun=dlsym(pdlHandle,"StrNlen");pszErr=dlerror();if(pszErr!=NULL){printf("%s\n",pszErr);return0;}printf("Thestringis:%s\n",str);ulLength=pStrlenFun(str);//直接使用函數(shù)指針,相當于調(diào)用庫函數(shù)

printf("Thestringlengthis:%d(useStrlen)\n",ulLength);ulLength=pStrnlenFun(str,10);printf("Thestringlengthis:%d(useStrNlen)\n",ulLength);

dlclose(pdlHandle);//關(guān)閉共享庫

return0;}創(chuàng)建顯示調(diào)用動態(tài)庫rm-flibstrdl.sorm-f*.omain#gcc-fpic-sharedStrlen.cStrnlen.c-olibstr.sogcc-c-fpicStrlen.cgcc-c-fpicStrnlen.c#創(chuàng)建動態(tài)鏈接庫gcc-sharedStrlen.oStrnlen.o-olibstrdl.sogcc-cmain_dl.c-I.#必須同時加入strdl和dl庫支持gccmain_dl.o-L.-lstrdl

-ldl-omain_dl運行顯示調(diào)用實例代碼優(yōu)化Gcc代碼優(yōu)化(1)代碼優(yōu)化指的是編譯器通過分析源代碼,找出其中尚未達到最優(yōu)的部分,然后對其重新進行組合,目的是改善程序的執(zhí)行性能。GCC提供的代碼優(yōu)化功能非常強大,它通過編譯選項-On來控制優(yōu)化代碼的生成,其中n是一個代表優(yōu)化級別的整數(shù)。對于不同版本的GCC來講,n的取值范圍及其對應的優(yōu)化效果可能并不完全相同,比較典型的范圍是從0變化到2或3。編譯時使用選項-O可以告訴GCC同時減小代碼的長度和執(zhí)行時間,其效果等價于-O1。在這一級別上能夠進行的優(yōu)化類型雖然取決于目標處理器,但一般都會包括線程跳轉(zhuǎn)(ThreadJump)和延遲退棧(DeferredStackPops)兩種優(yōu)化。選項-O2告訴GCC除了完成所有-O1級別的優(yōu)化之外,同時還要進行一些額外的調(diào)整工作,如處理器指令調(diào)度等。選項-O3則除了完成所有-O2級別的優(yōu)化之外,還包括循環(huán)展開和其它一些與處理器特性相關(guān)的優(yōu)化工作。通常來說,數(shù)字越大優(yōu)化的等級越高,同時也就意味著程序的運行速度越快。許多Linux程序員都喜歡使用-O2選項,因為它在優(yōu)化長度、編譯時間和代碼大小之間,取得了一個比較理想的平衡點。

Gcc代碼優(yōu)化(2)不帶優(yōu)化

gcc-Walloptimize.c-ooptimize做了優(yōu)化gcc-Wall-Ooptimize.c-ooptimizetime借助Linux提供的time命令,可以大致統(tǒng)計出該程序在運行時所需要的時間,比較兩次時間#time./optimize代碼優(yōu)化實例一個做了大量浮點數(shù)除法的程序.#include<stdio.h>intmain(void){doublecounter;doubleresult;doubletemp;for(counter=0;counter<2000.0*2000.0*2000.0/20.0+2020;counter+=(5-1)/4){temp=counter/1979;result=counter;}

printf("Resultis%lf\n",result);

return0;}代碼優(yōu)化的結(jié)果比較Gcc代碼優(yōu)化(3)-O-O1-O2多優(yōu)化一些.除了涉及空間和速度交換的優(yōu)化選項,執(zhí)行幾乎所有的優(yōu)化工作.例如不進行循環(huán)展開(loopunrolling)和函數(shù)內(nèi)嵌(inlining).和-O選項比較,這個選項既增加了編譯時間,也提高了生成代碼的運行效果.-O3優(yōu)化的更多.除了打開-O2所做的一切,它還打開了-finline-functions選項.-O0不優(yōu)化.如果指定了多個-O選項,不管帶不帶數(shù)字,最后一個選項才是生效的選項.Gcc代碼優(yōu)化(4)避免優(yōu)化代碼場合:程序開發(fā)的時候優(yōu)化等級越高,消耗在編譯上的時間就越長,因此在開發(fā)的時候最好不要使用優(yōu)化選項,只有到軟件發(fā)行或開發(fā)結(jié)束的時候,才考慮對最終生成的代碼進行優(yōu)化。資源受限的時候一些優(yōu)化選項會增加可執(zhí)行代碼的體積,如果程序在運行時能夠申請到的內(nèi)存資源非常緊張(如一些實時嵌入式設備),那就不要對代碼進行優(yōu)化,因為由這帶來的負面影響可能會產(chǎn)生非常嚴重的后果。跟蹤調(diào)試的時候在對代碼進行優(yōu)化的時候,某些代碼可能會被刪除或改寫,或者為了取得更佳的性能而進行重組,從而使跟蹤和調(diào)試變得異常困難。

交叉開發(fā)GCC在其它平臺的gccgcc是一個強大,開源的編譯器,因此被人移植多種CPU,多個操作系統(tǒng)下.如移植Windows下的mingW,Cygwingcc.exe幾乎在每種CPU,如ARM,MIPS,PowerPC等都有相應版本,而且在很多時候是唯一的編譯器,如龍芯.gcc還有一個強大的功能,即交叉編譯.即在A的操作系統(tǒng)下,編譯B操作系統(tǒng)下的程序.如嵌入式操作下x86的redhat9.0下去編譯ARM下的Arm-Linux的程序用于交叉開發(fā)的gcc在arm下開發(fā)的gcc通常叫arm-linux-gcc將arm-linux-gcc解壓后安裝將arm-linux-gcc其路徑加入系統(tǒng)PATH中將所有需要gcc的地方改成arm-linux-gcc重新編譯,即可完成簡單的移植在嵌入式中,通常需要-static靜態(tài)編譯.編譯后的可執(zhí)行程序可用U盤或FTP上傳到ARM開發(fā)板上課內(nèi)練習,將上一次課堂練習結(jié)果移植到開發(fā)板上注意,首先修改開發(fā)HOST的對應用戶的.bash_profile,假設是用戶hxy,則在/home/hxy/.bash_profile的PATH改成如下定義PATH=/usr/local/arm/2.95.3/bin:$PATH這樣才可以直接用arm-linux-gcc常見錯誤或警告dl_list.h:42:7:warning:nonewlineatendoffile這個通常是由于源碼里最后一行不是UNIX文本字符要求的空行,造成,這不影響最終編譯結(jié)果,如果想去掉,直接在源碼中加入一個空行即可test_link.o(.text+0x308):Infunction`test2'::undefinedreferenceto`dl_save_to_file‘表示在最終鏈接時,沒有找到dl_save_to_file這個函數(shù)的目標代碼,原因有多種,如沒有把這個源碼包含進來,系統(tǒng)函數(shù)的筆誤.找不到對應鏈接庫main.c:8:47:String.h:Nosuchfileordirectory某個頭文件找不到,很大可能性是沒有用-I參數(shù)把String.h所有在目錄加入進來../main:errorwhileloadingsharedlibraries:libstr.so:cannotopensharedobjectfile:Nosuchfileordirectory應用程序找不到自己鏈接的動態(tài)庫libstr.so,需要把libstr.so加入到環(huán)境變量LD_LIBRARY_PATH中程序運行常見錯誤1在busybox下運行程序,/usr/bin/boa:/usr/bin/boa:1:Syntaxerror:"("unexpected最大可以是這個程序是用x86gcc編譯的程序,然后在Arm-Linux運行時,被不匹配的strip課堂作業(yè)請開發(fā)一個程序,使用結(jié)構(gòu)定義structstudent{intno;/*學號*/charname[64];/*名稱*/floatheight;/*身高*/};要求創(chuàng)建3個學生定義,并給三個學生的三個成員都賦上值,用一個printf把一個學生的三個值打印出來,依次把所有學生信息顯示要求用vi編輯,并用gcc在Linux下編譯,測試通過課堂練習開發(fā)一個庫函數(shù),要求能對字符串的進行轉(zhuǎn)大寫轉(zhuǎn)換.要求把庫函數(shù),編譯成靜態(tài)和動態(tài)鏈接庫各一個,取名libtu.a,libtu.so編寫一個測試程序,要求能測試libtu測試庫函數(shù)把上述過程寫成一個Shell腳本,一次性執(zhí)行謝謝,請?zhí)釂栐诏偪竦臅r代把握未來課程目標學習使用字符界面gdb來調(diào)試Linux程序gdb高級應用圖形gdb界面-dddGdb簡介GDB是一個強大的命令行調(diào)試工具。大家知道命令行的強大就是在于,其可以形成執(zhí)行序列,形成腳本。UNIX下的軟件全是命令行的,這給程序開發(fā)提代供了極大的便利,命令行軟件的優(yōu)勢在于,它們可以非常容易的集成在一起,使用幾個簡單的已有工具的命令,就可以做出一個非常強大的功能。GDB相對圖形界面的VC++等,命令比較難記,這是命令行界面一大缺點Linux也有基于GDB圖形界面的調(diào)試器,如gdbinsight,DDD.GDB功能啟動你的程序,可以按照你的自定義的要求隨心所欲的運行程序??勺尡徽{(diào)試的程序在你所指定的調(diào)置的斷點處停住。(斷點可以是條件表達式)當程序被停住時,可以檢查此時你的程序中所發(fā)生的事。動態(tài)的改變你程序的執(zhí)行環(huán)境GDB與VC++調(diào)試命令的對比GDB幫助象大多部復雜Linux程序一樣,GDB是通過內(nèi)部命令來完成調(diào)試工作gdb的命令很多,gdb把之分成許多個種類.help命令只是例出gdb的命令種類,如果要看種類中的命令,可以使用help<class>命令,如:helpbreakpoints,查看設置斷點的所有命令。也可以直接help<command>來查看命令的幫助。gdb中,輸入命令時,可以不用打全命令,只用打命令的前幾個字符就可以了,當然,命令的前幾個字符應該要標志著一個唯一的命令在gdb下,你可以敲擊兩次TAB鍵來補齊命令的全稱,如果有重復的,那么gdb會把其例出來。GDB測試樣例編譯測試程序,一定要加上-g參數(shù),為可執(zhí)行文件加上調(diào)試信息gcc-gtst.c-otst啟動GDB的方式gdb<program>

program也就是你的執(zhí)行文件,一般在當前目錄下gdb<program>core用gdb同時調(diào)試一個運行程序和core文件,core是程序非法執(zhí)行后coredump后產(chǎn)生的文件gdb<program><PID>如果你的程序是一個服務程序,那么你可以指定這個服務程序運行時的進程ID。gdb會自動attach上去,并調(diào)試他。program應該在PATH環(huán)境變量中搜索得到。操作GDB常見命令GDB的啟動選項GDB啟動時,可以加上一些GDB的啟動選項--symbols<file>-s<file>

從指定文件中讀取符號表。-sefile

從指定文件中讀取符號表信息,并把他用在可執(zhí)行文件中。--core<file>

-c<file>

調(diào)試時coredump的core文件。--directory<directory>

-d<directory>

加入一個源文件的搜索路徑。默認搜索路徑是環(huán)境變量中PATH所定義的路徑。fileprogram詳細的開關(guān)可以用gdb--helpgdb的基本調(diào)試調(diào)試器的基本功能任何一種調(diào)試器,都必須具備如下基本功能建立可執(zhí)行程序與源碼的聯(lián)系(查看源碼)設置斷點執(zhí)行行基本的調(diào)試命令程序暫停后,查看各種信息查看源程序

GDB可以打印出所調(diào)試程序的源代碼,當然,在程序編譯時一定要加上-g的參數(shù),把源程序信息編譯到執(zhí)行文件中。當程序停下來以后,GDB會報告程序停在了那個文件的第幾行上。你可以用list命令來打印程序的源代碼??梢钥s寫為llist<linenum>

顯示程序第linenum行的周圍的源程序。list<function>

顯示函數(shù)名為function的函數(shù)的源程序。list

顯示當前行后面的源程序。list-

顯示當前行前面的源程序。一般是打印當前行的上5行和下5行,如果顯示函數(shù)是是上2行下8行,默認是10行,當然,你也可以定制顯示的范圍,使用下面命令可以設置一次顯示源程序的行數(shù)。setlistsize<count>

設置一次顯示源代碼的行數(shù)。setlistsize20設置顯示一次20行showlistsize

查看當前l(fā)istsize的設置。

查看源程序(2)list命令還有下面的用法list<first>,<last>

顯示從first行到last行之間的源代碼。list,<last>

顯示從當前行到last行之間的源代碼。list+

往后顯示源代碼。

一般來說在list后面可以跟以下這們的參數(shù):<linenum>行號。

<+offset>當前行號的正偏移量。

<-offset>當前行號的負偏移量。

<filename:linenum>哪個文件的哪一行。lgdb_tst.c:20<function>函數(shù)名。

<filename:function>

哪個文件中的哪個函數(shù)lgdb_tst.c:main<*address>程序運行時的語句在內(nèi)存中的地址。l*0x0804835a調(diào)試程序執(zhí)行g(shù)dbgdbgdb_tst設置斷點通常至少要設一個斷點,要不然gdb會直接運行到程序結(jié)束.bmain#在主函數(shù)入口設斷點設置命令行參數(shù)如果程序需要用到命令行參數(shù),直接在gdb命令是無法輸入setargs

可指定運行時參數(shù)。如:gdb>setargs1020304050開始調(diào)試進入gdb提示符后,gdb并沒有進調(diào)試狀態(tài)需要用r,即run進行調(diào)試在GDB中運行程序

當以gdb<program>方式啟動gdb后,gdb會在PATH路徑和當前目錄中搜索<program>的源文件。如要確認gdb是否讀到源文件,可使用l或list命令,看看gdb是否能列出源代碼。在gdb中,運行程序使用r或是run命令。程序的運行,你有可能需要設置下面四方面的事。程序運行參數(shù)。setargs可指定運行時參數(shù)。如:setargs1020304050運行環(huán)境path<dir>可設定程序的運行路徑。showpaths查看程序的運行路徑。setenvironmentvarname[=value]設置環(huán)境變量。如:setenvUSER=hchenshowenvironment[varname]查看環(huán)境變量。工作目錄。cd<dir>

相當于shell的cd命令。pwd顯示當前的所在目錄。程序的輸入輸出infoterminal顯示你程序用到的終端的模式。使用重定向控制程序輸出。如:run>outfiletty命令可以指寫輸入輸出的終端設備。如:tty/dev/ttyb常用調(diào)試命令

當程序被停住了,你可以用continue命令恢復程序的運行直到程序結(jié)束,或下一個斷點到來。也可以使用step或next命令單步跟蹤程序。continue[ignore-count]

c[ignore-count]

fg[ignore-count]

恢復程序運行,直到程序結(jié)束,或是下一個斷點到來。ignore-count表示忽略其后的斷點次數(shù)。continue,c,fg三個命令都是一樣的意思。step<count>

單步跟蹤,如果有函數(shù)調(diào)用,他會進入該函數(shù)。進入函數(shù)的前提是,此函數(shù)被編譯有debug信息。很像VC等工具中的stepin。后面可以加count也可以不加,不加表示一條條地執(zhí)行,加表示執(zhí)行后面的count條指令,然后再停住。next<count>

同樣單步跟蹤,如果有函數(shù)調(diào)用,他不會進入該函數(shù)。很像VC等工具中的stepsetstep-mode

setstep-modeon

打開step-mode模式,于是,在進行單步跟蹤時,程序不會因為沒有debug信息而不停住。這個參數(shù)有很利于查看機器碼。常用調(diào)試命令(2)setstep-modoff

關(guān)閉step-mode模式。finish

運行程序,直到當前函數(shù)完成返回。并打印函

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論