版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第四章 UNIX下的C語言開發(fā)環(huán)境,,6.1 程序設(shè)計(jì)環(huán)境,學(xué)習(xí)程序設(shè)計(jì)從程序語言開始,但還應(yīng)了解程序執(zhí)行和程序與外界的交互問題。,1.理想態(tài)的程序運(yùn)行環(huán)境,,用戶程序直接控制和使用各種設(shè)備,完成各種操作。,針對(duì)一個(gè)簡(jiǎn)單程序:,main(){ int c; while ( ( c=getchar()) != EOF )putchar(c);},,認(rèn)為執(zhí)行過程為:,在單用戶單任務(wù)環(huán)境中基本符合。,2.
2、多任務(wù)環(huán)境下程序執(zhí)行,多任務(wù)中每一時(shí)刻都會(huì)有多個(gè)用戶程序提出訪問請(qǐng)求,因此會(huì)有:,,如此混亂的情況,程序?qū)o法運(yùn)行。,為使多道環(huán)境中的程序正確執(zhí)行,需要OS管理。,,用戶程序需要系統(tǒng)核心區(qū)程序的管理,達(dá)到各自任務(wù)的執(zhí)行。,6.2 基于系統(tǒng)支持的程序設(shè)計(jì),,1. 建立系統(tǒng)編程的思想,理解多道環(huán)境程序執(zhí)行狀況,轉(zhuǎn)換用戶程序是執(zhí)行主體的認(rèn)識(shí)。 了解OS可提供的服務(wù)及服務(wù)方式。 充分利用OS提供服務(wù)功能解決實(shí)際問題。 盡量使編寫的程序最大
3、限度的滿足系統(tǒng)平臺(tái)的支持能力。,1. gcc 與 gdb,1.1 UNIX和C語言C 是一種在 UNIX 操作系統(tǒng)的早期就被廣泛使用的通用編程語言,它最早是由貝爾實(shí)驗(yàn)室的 Dennis Ritchie 為了 UNIX 的輔助開發(fā)而寫的。C 是所有版本的UNIX上的系統(tǒng)語言。幾乎任何一種計(jì)算機(jī)上都有至少一種能用的 C 編譯器
4、; 并且它的語法和函數(shù)庫在不同的平臺(tái)上都是統(tǒng)一的。80年代末期美國國家標(biāo)準(zhǔn)協(xié)會(huì) (American National Standards Institute)發(fā)布了一個(gè)被稱為 ANSI C 的 C 語言標(biāo)準(zhǔn),這保證了在不同平臺(tái)上的C的一致性。,7,1. gcc 與 gdb,1.2 GNU C編譯器GNU C 編譯
5、器(gcc)是一個(gè)全功能的 ANSI C 兼容編譯器,它是所有UNIX系統(tǒng)可用的C編譯器。gcc是可以在多種硬體平臺(tái)上編譯出可執(zhí)行程序的超級(jí)編譯器,其執(zhí)行效率與一般的編譯器相比平均效率要高20%~30%。,8,3.1 LINUX下C語言編程概述,1. gcc 與 gdb,gcc編譯過程:預(yù)處理,對(duì)源代碼文件中的文件包含(include)、預(yù)編譯語句(如宏定義define等)進(jìn)行分析。編譯,就是把C
6、/C++代碼“翻譯”成匯編代碼。匯編,將第二步輸出的匯編代碼翻譯成符合一定格式的機(jī)器代碼,生成以.o為后綴的目標(biāo)文件。鏈接,將上步生成的目標(biāo)文件和系統(tǒng)庫的目標(biāo)文件和庫文件鏈接起來,最終生成了可以在特定平臺(tái)運(yùn)行的可執(zhí)行文件。,10,1. Gcc編譯流程解析如本章開頭提到的,Gcc的編譯流程分為了4個(gè)步驟,分別為:· 預(yù)處理(Pre-Processing);· 編譯(Compiling);· 匯編(
7、Assembling);· 鏈接(Linking)。下面就具體來查看一下Gcc是如何完成4 個(gè)步驟的。首先,有以下hello.c源代碼:#includeint main(){printf("Hello! This is our embedded world!\n");return 0;},3.3 Gcc編譯器,(1)預(yù)處理階段在該階段,編譯器將上述代碼中的stdio.h編譯進(jìn)來,并且用戶
8、可以使用Gcc的選項(xiàng)“-E”進(jìn)行查看,該選項(xiàng)的作用是讓Gcc在預(yù)處理結(jié)束后停止編譯過程。[root@localhost Gcc]# Gcc –E hello.c –o hello.i在此處,選項(xiàng)“-o”是指目標(biāo)文件,由上表可知,“.i”文件為已經(jīng)過預(yù)處理的C 原始程序。以下列出了hello.i文件的部分內(nèi)容:typedef int (*__gconv_trans_fct) (struct __gconv_step *,struc
9、t __gconv_step_data *, void *,__const unsigned char *,__const unsigned char **,__const unsigned char *, unsigned char **,size_t *);…,,# 2 "hello.c" 2int main(){printf("Hello! This is our embedded w
10、orld!\n");return 0;}由此可見,Gcc確實(shí)進(jìn)行了預(yù)處理,它把“stdio.h”的內(nèi)容插入到hello.i文件中。,(2)編譯階段接下來進(jìn)行的是編譯階段,在這個(gè)階段中,Gcc 首先要檢查代碼的規(guī)范性、是否有語法錯(cuò)誤等,以確定代碼的實(shí)際要做的工作,在檢查無誤后,Gcc 把代碼翻譯成匯編語言。用戶可以使用“-S”選項(xiàng)來進(jìn)行查看,該選項(xiàng)只進(jìn)行編譯而不進(jìn)行匯編,生成匯編代碼。[root@localhost G
11、cc]# Gcc –S hello.i –o hello.s以下列出了hello.s的內(nèi)容,可見Gcc已經(jīng)將其轉(zhuǎn)化為匯編了,感興趣的讀者可以分析一下這一行簡(jiǎn)單的C語言小程序是如何用匯編代碼實(shí)現(xiàn)的。.file "hello.c“.section .rodata.align 4.LC0:.string "Hello! This is our embedded world!".text.globl
12、 main.type main, @functionmain:pushl %ebpmovl %esp, %ebpsubl $8, %espandl $-16, %espmovl $0, %eaxaddl $15, %eax.section .note.GNU-stack,"",@progbits,(3)匯編階段匯編階段是把編譯階段生成的“.s”文件轉(zhuǎn)成目標(biāo)文件,讀者在此可使用選項(xiàng)“-c”就可看到
13、匯編代碼已轉(zhuǎn)化為“.o”的二進(jìn)制目標(biāo)代碼了。如下所示:[root@localhost Gcc]# Gcc –c hello.s –o hello.o,Gcc編譯器,(4)鏈接階段在成功編譯之后,就進(jìn)入了鏈接階段。在這里涉及到一個(gè)重要的概念:函數(shù)庫。讀者可以重新查看這個(gè)小程序,在這個(gè)程序中并沒有定義“printf”的函數(shù)實(shí)現(xiàn),且在預(yù)編譯中包含進(jìn)的“stdio.h”中也只有該函數(shù)的聲明,而沒有定義函數(shù)的實(shí)現(xiàn),那么,是在哪里實(shí)現(xiàn)“prin
14、tf”函數(shù)的呢?最后的答案是:系統(tǒng)把這些函數(shù)實(shí)現(xiàn)都被做到名為libc.so.6的庫文件中去了,在沒有特別指定時(shí),Gcc 會(huì)到系統(tǒng)默認(rèn)的搜索路徑“/usr/lib”下進(jìn)行查找,也就是鏈接到libc.so.6庫函數(shù)中去,這樣就能實(shí)現(xiàn)函數(shù)“printf”了,而這也就是鏈接的作用。函數(shù)庫一般分為靜態(tài)庫和動(dòng)態(tài)庫兩種。靜態(tài)庫是指編譯鏈接時(shí),把庫文件的代碼全部加入到可執(zhí)行文件中,因此生成的文件比較大,但在運(yùn)行時(shí)也就不再需要庫文件了。其后綴名一般為“.
15、a”。動(dòng)態(tài)庫與之相反,在編譯鏈接時(shí)并沒有把庫文件的代碼加入到可執(zhí)行文件中,而是在程序執(zhí)行時(shí)由運(yùn)行時(shí)鏈接文件加載庫,這樣可以節(jié)省系統(tǒng)的開銷。動(dòng)態(tài)庫一般后綴名為“.so”,如前面所述的libc.so.6就是動(dòng)態(tài)庫。Gcc在編譯時(shí)默認(rèn)使用動(dòng)態(tài)庫。完成了鏈接之后,Gcc就可以生成可執(zhí)行文件,如下所示。[root@localhost Gcc]# Gcc hello.o –o hello運(yùn)行該可執(zhí)行文件,出現(xiàn)正確的結(jié)果如下。[root@loc
16、alhost Gcc]# ./helloHello! This is our embedded world!,Gcc編譯選項(xiàng):,Gcc編譯器,1. UNIX下的C語言開發(fā)環(huán)境,gcc遵循的文件類型規(guī)定 .c為后綴的文件,C語言源代碼文件; .a為后綴的文件,是由目標(biāo)文件構(gòu)成的檔案庫文件; .C,.cc或.cxx 為后綴的文件,是C++源代碼文件; .h為后綴的文件,是程序所包含的頭文件;.i 為后綴的文件,是已經(jīng)預(yù)處理過的C
17、源代碼文件;.ii為后綴的文件,是已經(jīng)預(yù)處理過的C++源代碼文件;.m為后綴的文件,是Objective-C源代碼文件; .o為后綴的文件,是編譯后的目標(biāo)文件; .s為后綴的文件,是匯編語言源代碼文件;.S為后綴的文件,是經(jīng)過預(yù)編譯的匯編語言源代碼文件。,18,頭文件,頭文件是用來提供常量的定義和系統(tǒng)和函數(shù)調(diào)用的聲明,這些頭文件通常放在/usr/include和其子目錄中。根據(jù)不同的Linux版本,頭文件可能放在/usr/in
18、clude/sys和/usr/include/linux.#include ,庫函數(shù),庫函數(shù)是一些預(yù)先編譯好的函數(shù)的集合,這些函數(shù)可以有很好的重用性。通常來講,它們包含有相關(guān)的函數(shù)集合來完成一項(xiàng)常用任務(wù)。典型的庫函數(shù)有屏幕處理函數(shù) (curses和ncurses庫)和數(shù)據(jù)庫訪問函數(shù)(dbm庫)。標(biāo)準(zhǔn)系統(tǒng)函數(shù)通常存放在/lib和/usr/lib中。C編譯器需要被告知搜索哪個(gè)庫,否則缺省情況下只搜索標(biāo)準(zhǔn)庫。傳統(tǒng)靜態(tài)庫 .a E
19、xamples are /usr/lib/libc.a and /usr/X11/lib/libX11.a for the standard C library and the X11 library共享庫 .so On a typical Linux system, the shared version of the standard math library is /usr/lib/libm.so,1. g
20、cc 與 gdb,1.5 gdb調(diào)試和分析選項(xiàng)gdb 基本命令file 裝入想要調(diào)試的可執(zhí)行文件;kill 終止正在調(diào)試的程序;list 列出產(chǎn)生執(zhí)行文件的源代碼的一部分;next 執(zhí)行一行源代碼但不進(jìn)入函數(shù)內(nèi)部;step 執(zhí)行一行源代碼而且進(jìn)入函數(shù)內(nèi)部;run 執(zhí)行當(dāng)前被調(diào)試的程序;quit 終止 gdb ;watch
21、 使你能監(jiān)視一個(gè)變量的值而不管它何時(shí)被改變;break 在代碼里設(shè)置斷點(diǎn), 這將使程序執(zhí)行到這里時(shí)被掛起;make 使你能不退出 gdb 就可以重新產(chǎn)生可執(zhí)行文件;shell 使你能不離開 gdb 就執(zhí)行 UNIX shell 命令.,21,1. gcc 與 gdb,gdb調(diào)試舉例,/* gdbtest.c */
22、#include int sum(int m);int main(int argc, char **argv){int i, n = 0;sum(50);for(i=1; i<=50; i++){n += i;}printf(“The sum of 1-50 is %d\n”, n);},int sum(int m){int i, n = 0;for(i=1; i<=m; i++)
23、{n += i;}printf(“The sum of 1-%d is %d\n”, m, n);},例:$ gcc -Wall -g gdbtest.c -o gdbtest,22,1. gcc 與 gdb,1. 啟動(dòng)gdb開始調(diào)試,例1:$ gdb gdbtest,例2:$ gdb(gdb) file gdbtest,23,1. gcc 與 gdb,2. 在gdb中查看源代碼,例:(gdb) list,li
24、st也可以縮寫為l,24,1. gcc 與 gdb,3. 在gdb中設(shè)置斷點(diǎn),例1:(gdb) break 9,break也可以縮寫為b,注意:在gdb中利用行號(hào)設(shè)置斷點(diǎn),是指代碼運(yùn)行到對(duì)應(yīng)行號(hào)之前暫停;gdb中可以設(shè)置多個(gè)斷點(diǎn)。,25,1. gcc 與 gdb,3. 在gdb中設(shè)置斷點(diǎn),例2:(gdb) break sum,設(shè)置函數(shù)斷點(diǎn),在函數(shù)體開始處,例3:(gdb) break 10 if i==10,設(shè)置條件斷點(diǎn),26,
25、1. gcc 與 gdb,4. 開看斷點(diǎn)情況,例:(gdb) info break,27,1. gcc 與 gdb,5. 運(yùn)行代碼,例:(gdb) run,run也可以縮寫為r,28,1. gcc 與 gdb,6. 查看變量,例:(gdb) print i,print也可以縮寫為p;i為變量名,“$N”是當(dāng)前變量值的引用標(biāo)記,29,1. gcc 與 gdb,7. 單步運(yùn)行,單步運(yùn)行可以使用命令“step”和“next”,它們之間的
26、區(qū)別在于:若有函數(shù)調(diào)用的時(shí)候“step”會(huì)進(jìn)入函數(shù)體,而“next”不會(huì)進(jìn)入該函數(shù);,8. 恢復(fù)程序運(yùn)行,使用命令“continue”可以恢復(fù)程序正常運(yùn)行,直到遇到下一個(gè)斷點(diǎn)或者到程序結(jié)束;,gdb中程序有“運(yùn)行”、“暫?!焙汀巴V埂比N狀態(tài)。“暫?!睜顟B(tài)時(shí),函數(shù)的地址、參數(shù)、局部變量都被壓入“?!敝?,故可以查看函數(shù)的各種屬性;函數(shù)處于“停止”狀態(tài)時(shí),“?!睍?huì)自動(dòng)撤銷,也就無法查看函數(shù)的信息了。,30,2. make工程管理器,2.1
27、為什么要使用make?工作量問題:對(duì)于擁有多個(gè)(上百個(gè))源文件的軟件項(xiàng)目,只需編寫一次編譯過程,而不需要在每次源文件修改后重復(fù)輸入眾多的文件名和編譯命令進(jìn)行編譯;效率問題:make能夠根據(jù)文件的時(shí)間戳自動(dòng)發(fā)現(xiàn)更新過的源文件,并通過讀入Makefile文件來對(duì)更新的源文件進(jìn)行編譯而對(duì)其它文件只進(jìn)行鏈接操作。,31,2. make命令,2.2 Makefile的格式Makefile是make讀入的唯一配置文件,Makefile文件
28、通常包含如下內(nèi)容:需要由make創(chuàng)建的目標(biāo)體(target),通常是目標(biāo)文件或可執(zhí)行文件;要?jiǎng)?chuàng)建的目標(biāo)體所依賴的文件(dependency_file);創(chuàng)建每個(gè)目標(biāo)體時(shí)需要運(yùn)行的命令(commmand)。,Makefile格式:target: dependency_file command,command之前必須有個(gè)“tab”,32,4. 鏈接特殊函數(shù)庫,/*filename is temp.c */
29、# include int main(int argc,char *argv) { double value; value=log(argc); printf("Value:%f \n",value); } 用命令:gcc –o temp temp.c 編譯時(shí)出錯(cuò)。修改命令: gcc –o temp temp.c –lm這里指明編譯時(shí)與數(shù)學(xué)庫libm.a相鏈接,則可正
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
評(píng)論
0/150
提交評(píng)論