版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、第9章 Linux程序設計基礎 本章學習目標本章學習目標通過對本章的學習,讀者應該掌握以下主要內(nèi)容:Linux編程風格Linux下IDE的使用Linux下使用GNU cc開發(fā)應用程序Linux程序的調(diào)試Linux下使用RCS/CVS來管理源程序Linux下軟件打包9.1 概述概述 9.1.1 Linux編程編程 Linux軟件開發(fā)一直在Internet環(huán)境下講行。這個環(huán)境是全球性的,編程人員來自世界各地。只要能夠訪問Web站點,就可以啟動一個以Linux為基礎的軟件項目。Linux開發(fā)工作經(jīng)常是在Linux用戶決定共同完成一個項目時開始的。當開發(fā)工作完成后,該軟件就被放到Internet站點上
2、,任何用戶都可以訪問和下載它。由于這個活躍的開發(fā)環(huán)境,新的以Linux為基礎的軟件功能日益強大,而且呈現(xiàn)爆炸式的增長態(tài)勢。 大多數(shù)Linux軟件是經(jīng)過自由軟件基金會(Free Software Foundation)提供的GNU(GNU 即 GNUs not UNIX)公開認證授權(quán)的,因而通常被稱作GNU軟件。GNU軟件免費提供給用戶使用,并被證明是非常可靠和高效的。許多流行的Linux實用程序如C編譯器、shell和編輯器都是GNU軟件應用程序。 Linux程序需要首先轉(zhuǎn)化為低級機器語言即所謂的二進制代碼以后,才能被操作系統(tǒng)執(zhí)行。例如編程時,先用普通的編程語言生成一系列指令,這些指令可被翻譯
3、為適當?shù)目蓤?zhí)行應用程序的二進制代碼。這個翻譯過程可由解釋器一步步來完成,或者也可以立即由編譯器明確地完成。shell編程語言如BASH、TCSH、GAWK、Perl、Tcl和Tk都利用自己的解釋器。用這些語言編制的程序盡管是應用程序文件,但可以直接運行。編譯器則不同,它將生成一個獨立的二進制代碼文件然后才可以運行。 9.1.2 Linux編程風格編程風格 (1)函數(shù)返回類型說明和函數(shù)名分兩行放置,函數(shù)起始字符和函數(shù)開頭左花括號放到最左邊。(2)盡量不要讓兩個不同優(yōu)先級的操作符出現(xiàn)在相同的對齊方式中,應該附加額外的括號使得代碼縮進可以表示出嵌套。 (3)按照如下方式排版do-while語句: (
4、4)每個程序都應該以一段簡短的說明其功能的注釋開頭。 (5)請為每個函數(shù)書寫注釋,說明函數(shù)是做什么的,需要哪些入口參數(shù),參數(shù)可能值的含義和用途。如果用了非常見的、非標準的東西,或者可能導致函數(shù)不能工作的任何可能的值,應該進行特殊說明。如果存在重要的返回值,也需要說明。 (6)不要聲明多個變量時跨行,每一行都以一個新的聲明開頭。 (7)當一個if中嵌套了另一個if-else時,應用花括號把if-else括起來。 (8)要在同一個聲明中同時說明結(jié)構(gòu)標識和變量或者結(jié)構(gòu)標識和類型定義(typedef)。先定義變量,再使用。 1 1GNUGNU風格風格 (9)盡量避免在if的條件中進行賦值。 (10)請
5、在名字中使用下劃線以分割單詞,盡量使用小寫;把大寫字母留給宏和枚舉常量,以及根據(jù)統(tǒng)一慣例使用的前綴。例如,應該使用類似ignore_space_change_flag的名字;不要使用類似iCantReadThis的名字。(11)用于表明一個命令行選項是否給出的變量應該在選項含義的說明之后,而不是選項字符之后被命名。 2 2Linux Linux 內(nèi)核編程風格內(nèi)核編程風格 (1)Linux內(nèi)核縮進風格是8個字符。 (2)Linux內(nèi)核風格采用K&R標準,將開始的大括號放在一行的最后,而將結(jié)束的大括號放在一行的第一位。(3)命名盡量簡潔。不應該使用諸如ThisVariableIsATemporar
6、yCounter之類的名字。應該命名為tmp,這樣容易書寫,也不難理解。但是命名全局變量,就應該用描述性命名方式,例如應該命名“count_active_users()”,而不是“cntusr()”。本地變量應該避免過長。 (4)函數(shù)最好短小精悍,一般來說不要讓函數(shù)的參數(shù)多于個,否則應該嘗試分解這個過于復雜的函數(shù)。 (5)通常情況,注釋說明代碼的功能,而不是其實現(xiàn)原理。避免把注釋插到函數(shù)體內(nèi),而寫到函數(shù)前面,說明其功能,如果這個函數(shù)的確很復雜,其中需要有部分注釋,可以寫些簡短的注釋來說明那些重要的部分,但是不能過多。 9.2 IDE使用使用 9.2.1 VIM編輯器編輯器 1 1VIMVIM的
7、簡介的簡介 VI是Linux世界里最常用的全屏編輯器,所有的Linux機器都提供該編輯器,而Linux里提供的是VI的加強版VIM,但同VI是完全兼容。VI的原意是“visual interface”,即可視編輯器,用戶鍵入的內(nèi)容會立即被顯示出來、而且其強大的編輯功能可以同任何一種最新的編輯器相媲美。它在Linux上的地位就仿佛Edit程序在DOS上一樣。它可以執(zhí)行輸出、刪除、查找、替換、塊操作等眾多文本操作,而且用戶可以根據(jù)需要對其進行定制,這是其他編輯程序所沒有的。VI不是一個排版程序,不象Word或WPS那樣可以對字體、格式、段落等其他屬性進行編排,它只是一個文本編輯程序。 2 2VIM
8、 VIM 的基本觀念的基本觀念 VIM有三種操作方式,分別是:命令方式插入方式命令行方式 3 3VIMVIM的進入與離開的進入與離開 在系統(tǒng)提示符“$”下鍵入命令VIM,后面跟上想要編輯(或者建立)的文件名,VIM 可以自動載入所要編輯的文件或是開啟一個新文件。 VIM的退出,可以在命令行方式下使用命令“:wq”或者“:q!”,前者的功能是寫文件并從VIM中退出,后者的功能是從VIM中退出,但不保存所作的修改(注意冒號)。 4 4VIMVIM的命令方式的命令方式 (1)光標移動 要對正文內(nèi)容進行修改,必須先把光標移動到要修改的內(nèi)容所在的位置,用戶除了通過按鍵盤的上、下、左、右箭頭鍵來移動光標,
9、還可以利用VIM提供的眾多字符組合鍵,在正文中移動光標,迅速達到指定的行或列,實現(xiàn)定位,常用的快捷鍵有:表9-1 (2)替換和刪除 將光標定位于文檔中指定位置后,可以用其他字符替換光標所指向的字符,或從當前光標位置刪除一個或多個字符,常用命令有:表9-2 (3)粘貼和復制 在VIM編輯器中,與Windows系統(tǒng)不同的是從正文中刪除的內(nèi)容(如字符、字段或行)并沒有真正丟失,而是被剪貼并復制到了一個內(nèi)存緩沖區(qū)中,用戶可將其粘貼到正文中的任意位置,完成這一操作的命令是:表9-3 (4)查找字符串 為了方便文檔的編輯,VIM提供了強大的字符串查找功能,要查找文件中指定字符或字段出現(xiàn)的位置,可以用該功能
10、直接進行搜索,搜索方法是:在命令行鍵入字符“/”,后面加上要搜索的字符串,然后按回車鍵,編輯程序?qū)?zhí)行正向搜索(從光標所在的位置向文件末尾方向),并在找到指定字符串后,將光標停在該字符串的開頭;鍵入n命令可以繼續(xù)執(zhí)行搜索,找出這一字符串下次出現(xiàn)的位置,用字符“?”取代“/”,可以實現(xiàn)反向搜索(從光標所在的位置向文件開頭方向),舉例說明如下:表9-5 (5)撤銷和重復 在編輯文檔的過程中,可以取消錯誤的編輯命令造成的后果,另外,如果用戶希望在新的光標位置再次執(zhí)行先前的編輯命令,可用重復命令。表9-6 5 5VIMVIM的插入方式的插入方式 (1)進入插入方式 在命令方式下正確定位光標之后,可用一
11、下命令切換到插入方式:表9-7 如果用戶想利用已有的文件內(nèi)容,可以使用命令“:ifilename”,則VIM將指定文件的內(nèi)容輸入當前光標的下一行,且VIM仍處于命令方式。 (2)退出插入方式 退出插入方式的方法是,按ESC鍵或組合鍵Ctrl+I (3)正文替換 除了幾種簡單的切換到插入方式的方法外,還有一些命令允許用戶在插入模式之前首先刪去一段文字,從而實現(xiàn)正文的替換,這些命令包括:表9-8 6 6VIMVIM的命令方式的命令方式 (1)行號與文件 編輯中文檔的每一行正文都有隱藏的行號,用下列命令可以移動光標到指定行:表9-9 在命令方式下,用戶可以規(guī)定命令操作的行號范圍,數(shù)值用來指定絕對行號
12、;字符“,”表示光標所在行的行號;字符“$”表示正文最后一行的行號,示例如下:表9-10 在命令方式下,用戶還可以對文件進行操作,允許從文件中讀取正文,或?qū)⒄膶懭胛募S妹钊缦拢罕?-11 9.2.1 VIM編輯器編輯器 1 1emacsemacs的簡介的簡介 emacs文本編輯器可以用來編輯文本、剪輯和粘貼文本內(nèi)容、提供個人日歷和日記,閱讀Usenet新聞、發(fā)送電子郵件,同時還是一種程序語言解釋器,可以編輯C、Lisp、Tev源代碼文件、以及Linux的Shell。 emacs是由 Richard Stallman發(fā)明的,這位發(fā)明者還創(chuàng)建了自由軟件基金會(Free Software F
13、oundation,簡稱FSF)。最初的emacs是用來編輯宏命令的,現(xiàn)已進一步擴充為 UNIX用戶中裝機用戶數(shù)量最大、功能最齊全的免費文本編輯器了。 emacs同VI不一樣,沒有編輯狀態(tài)和指令狀態(tài)之分,其最重要的概念是其獨特的緩沖區(qū),emacs編輯的所有文件都是放在緩沖區(qū)中的,emacs支持同時編輯多個緩沖區(qū),可以將一個文件在多個緩沖區(qū)中打開不同的拷貝,甚至其所有的在線幫助和文檔以及出錯信息都是作為一個緩沖區(qū)來顯示的,當然這些緩沖區(qū)是不可寫的,用戶可以在這些緩沖區(qū)之間拷貝和粘貼文本。并且一般所有的緩沖區(qū)在硬盤上都有一個以“#”開頭的備份文件,這樣在系統(tǒng)突然崩潰的時候可以即時將用戶的工作進行備
14、份。在編輯文件時,如果用戶在編輯一些特殊類型的文件,例如當用戶編輯擴展名為.c的C語言文件時,emacs會產(chǎn)生菜單選項c,向用戶提供一些針對編輯c程序特別有用的一些命令。當用戶編輯擴展名為.txt的文件則會多出菜單選項tex,讓用戶在編輯完tex文件后可以即時地觀看輸出并打印。首先介紹一下幾個常見的鍵盤操作符號的意義:所有的emacs的操作鍵都是由Control鍵(一般是鍵盤上的Ctrl鍵)和META鍵(一般是鍵盤上的Alt鍵)加上一些鍵的組合組成的,如果沒有Alt鍵,則可以用輸入一個Esc,再輸入相應的鍵來代替。例如: C-x:表示同時按住Ctrl鍵和x鍵。 C x:表示先按住Ctrl鍵,然
15、后釋放它,再按下x鍵。 M-x:表示同時按住Alt鍵和x鍵。 M x:表示先按住Alt鍵,釋放它,再按下x鍵。 2emacs的啟動和退出的啟動和退出 emacs可以用兩種方法啟動。第一種啟動emacs的方法是不裝載任何文本文件啟動emacs,輸入以下命令行:# emacs 在屏幕上會出現(xiàn)無任何文本emacs編輯窗口,如圖9-2所示。 如果用戶是初學者,最好的學習方法是:按下Ctrl-h鍵(即按住Ctrl鍵后不放,再按下h字母鍵),就會自動進入emacs的聯(lián)機幫助,在屏幕底部emacs命令行中會出現(xiàn)一個提示符,這時再按下字母鍵t和回車鍵,便進入了簡捷有效的emacs文本編輯器的教程。參照此教程的
16、步驟,用戶將對如何使用emacs有個概括的了解。 第二種啟動emacs的方法是通過裝載某一個文本文件啟動emacs,輸入以下命令行:# emacs filename如果裝載的文件不在當前目錄時必須輸入該文件名的全稱(包括所在目錄)。例如,當前目錄下有一個文本文件myfile.txt,用emacs對其編輯時,輸入命令行啟動emacs:# emacs myfile.txt 屏幕上將出現(xiàn)如圖9-3所示的emacs編輯窗口。 3emacs的基本操作的基本操作 (1)光標的移動下面列出emacs中的光標的移動情況及其鍵盤操作: M-b:光標移動到光標左邊的單詞的開始處。 M-f:光標移動到光標右邊的單詞
17、的開始處。 M-a:光標移動到當前句子的開始處。 M-e:光標移動到當前句子的結(jié)束處。 C-n:光標移動到下一行。 C-p:光標移動到上一行。 C-a:光標移動到行首。 C-e:光標移動到行尾。 M-:光標移動到文件尾。 M-編譯”命令進行程序的編譯,如圖9-15所示。如果程序沒有出錯,將看到Kdevelop下方的信息框之中顯示編譯成功的信息。 接著便可以執(zhí)行應用程序了,執(zhí)行“建立-執(zhí)行”命令進行程序的連接,如圖9-16所示。若沒有發(fā)生問題,就會在另一個窗口中看到程序的執(zhí)行結(jié)果,如圖9-17所示。 圖9-15 編譯應用程序 圖9-16 執(zhí)行應用程序 圖9-17 應用程序的執(zhí)行結(jié)果 9.3 使用
18、使用GNU cc開發(fā)應用程序開發(fā)應用程序 9.3.1 使用使用GNU cc 1gcc的簡介的簡介 gcc可以使程序員靈活地控制編譯過程。編譯過程一般可以分為下面四個階段,每個階段分別調(diào)用不同的工具進行處理,如圖9-18所示。 預處理鏈接編譯組譯源程序(*.c)可執(zhí)行文件預處理器編譯器組譯器連接器2gcc的版本信息的版本信息 一般來說,系統(tǒng)安裝后就已經(jīng)安裝和設定好了gcc。在shell的提示符下鍵入gcc v,屏幕上就會顯示出目前正在使用的gcc的版本,同時這可以確定系統(tǒng)所支持的是ELF還是a.out可執(zhí)行文件格式。 Linux系統(tǒng)中可執(zhí)行文件有兩種格式。第一種格式是a.out格式,這種格式用于
19、早期的Linux系統(tǒng)以及 Unix系統(tǒng)的原始格式。a.out來自于Unix C編譯程序默認的可執(zhí)行文件名。當使用共享庫時,a.out格式就會發(fā)生問題。把a.out格式調(diào)整為共享庫是一種非常復雜的操作,由于這個原因,一種新的文件格式被引入Unix系統(tǒng)5的第四版本和Solaris系統(tǒng)中。它被稱為可執(zhí)行和連接的格式(ELF)。這種格式很容易實現(xiàn)共享庫。 ELF格式已經(jīng)被Linux系統(tǒng)作為標準的格式采用。gcc編譯程序產(chǎn)生的所有的二進制文件都是ELF格式的文件(即使可執(zhí)行文件的默認名仍然是a.out)。較舊的a.out格式的程序仍然可以運行在支持ELF格式的系統(tǒng)上。 3gcc的使用的使用 gcc的使用
20、格式如下:$ gcc optionsfilenames其中filenames為所要編譯的程序源文件。 當使用gcc時,gcc會完成預處理、編譯、匯編和連接。前三步分別生成目標文件,連接時,把生成的目標文件鏈接成可執(zhí)行文件。gcc可以針對支持不同的源程序文件進行不同處理,文件格式以文件的后綴來識別,常見的如表9-1所示。 4使用優(yōu)化選項使用優(yōu)化選項 當用gcc編譯C代碼時,它會試著用最少的時間完成編譯并且使編譯后的代碼易于調(diào)試. 易于調(diào)試意味著編譯后的代碼與源代碼有同樣的執(zhí)行次序,編譯后的代碼沒有經(jīng)過優(yōu)化。有很多選項可用于告訴gcc,在耗費更多編譯時間和犧牲易調(diào)試性的基礎上,產(chǎn)生更小更快的可執(zhí)行
21、文件。這些選項中最典型的是-O和-O2選項。 -O選項告訴gcc對源代碼進行基本優(yōu)化。這些優(yōu)化在大多數(shù)情況下都會使程序執(zhí)行的更快。 -O2選項告訴gcc產(chǎn)生盡可能小和盡可能快的代碼。-O2選項將使編譯的速度比使用-O 時慢。但通常產(chǎn)生的代碼執(zhí)行速度會更快。 5使用調(diào)試和剖析選項使用調(diào)試和剖析選項 GCC 支持數(shù)種調(diào)試和剖析選項。在這些選項里最常用的是-g和-pg選項。-g選項告訴gcc產(chǎn)生能被GNU調(diào)試器使用的調(diào)試信息以便調(diào)試程序。gcc 提供了一個很多其他C編譯器里沒有的特性,在gcc里能使-g和-O(產(chǎn)生優(yōu)化代碼)連用。這一點非常有用,因為能在與最終產(chǎn)品盡可能相近的情況下調(diào)試代碼。同時使用
22、這兩個選項時必須清楚所寫的某些代碼已經(jīng)在優(yōu)化時被gcc作了改動。 -pg選項告訴gcc在程序里加入額外的代碼,執(zhí)行時,產(chǎn)生gprof用的剖析信息以顯示程序的耗時情況。 9.3.2使用使用GNU make編輯編輯makefile 1準備工作準備工作 要使用make,必須編寫一個叫做Makefile的文件,這個文件描述了軟件包中文件之間的關(guān)系,提供更新每個文件的命令。一般在一個軟件包里,通常是可執(zhí)行文件靠目標文件來更新,目標文件靠編譯源文件來更新。Makefile寫好之后,每次改變了某些源文件,只要執(zhí)行make命令:# make 所有必要的重新編譯將執(zhí)行。Make程序利用makefile中的數(shù)據(jù)和
23、每個文件的最后修改時間來確定那個文件需要更新,對于需要更新的文件,make程序執(zhí)行makefile數(shù)據(jù)中定義的命令來更新。 2makefile文件的基本結(jié)構(gòu)文件的基本結(jié)構(gòu) GNU make的主要功能是讀進一個文本文件makefile并根據(jù)makefile的內(nèi)容執(zhí)行一系列的工作。makefile的默認文件名為GNUmakefile、makefile或Makefile,當然也可以在make的命令行中指定別的文件名。如果不特別指定,make命令在執(zhí)行時將按順序查找默認的makefile文件。多數(shù)Linux程序員使用第三種文件名Makefile。因為第一個字母是大寫,通常被列在一個目錄的文件列表的最前
24、面。 Makefile是一個文本形式的數(shù)據(jù)庫文件,其中包含一些規(guī)則來告訴make處理哪些文件以及如何處理這些文件。這些規(guī)則主要是描述哪些文件(稱為target目標文件,不要和編譯時產(chǎn)生的目標文件相混淆)是從哪些別的文件(稱為dependency依賴文件)中產(chǎn)生的,以及用什么命令(command)來執(zhí)行這個過程。依靠這些信息,make會對磁盤上的文件進行檢查,如果目標文件的生成或被改動時的時間(稱為該文件時間戳)至少比它的一個依賴文件還舊的話,make就執(zhí)行相應的命令,以更新目標文件。目標文件不一定是最后的可執(zhí)行文件,可以是任何一個中間文件并可以作為其他目標文件的依賴文件。一個Makefile文
25、件主要含有一系列的規(guī)則,每條規(guī)則包含以下內(nèi)容。一個目標(target),即make最終需要創(chuàng)建的文件,如可執(zhí)行文件和目標文件;目標也可以是要執(zhí)行的動作,如“clean”。一個或多個依賴文件(dependency)列表,通常是編譯目標文件所需要的其他文件。 一系列命今(command),是make執(zhí)行的動作,通常是把指定的相關(guān)文件編譯成目標文件的編譯命令,每個命令占一行,且每個命令行的起始字符必須為TAB字符。 除非特別指定,否則make的工作目錄就是當前目錄。target是需要創(chuàng)建的二進制文件或目標文件,dependency是在創(chuàng)建target時需要用到的一個或多個文件的列表,命令序列是創(chuàng)建t
26、arget文件所需要執(zhí)行的步驟,比如編譯命令。Makefile規(guī)則的一般形式如下:target:dependency dependency(tab) 例如,有以下的Makefile文件:# 一個簡單的Makefile的例子# 以#開頭的為注釋行test:prog.o code.ogcc o test prog.o code.o prog.o:prog.c prog.h code.hgcc c prog.c o prog.o code.o:code.c code.hgcc c code.c o code.o clean:rm f *.o 上面的Makefile文件中共定義了四個目標:test、p
27、rog.o、code.o和clean。目標從每行的最左邊開始寫,后面跟一個冒號(:),如果有與這個目標有依賴性的其他目標或文件,把它們列在冒號后面,并以空格隔開。然后另起一行開始寫實現(xiàn)這個目標的一組命令。在Makefile中,可使用續(xù)行號()將一個單獨的命令行延續(xù)成幾行。但要注意在續(xù)行號()后面不能跟任何字符(包括空格和鍵)。一般情況下,調(diào)用make命令可輸入:# make targettarget是Makefile文件中定義的目標之一,如果省略target,make就將生成Makefile文件中定義的第一個目標。對于上面Makefile的例子,單獨的一個“make”命令等價于:# make
28、test 因為test是Makefile文件中定義的第一個目標,make首先將其讀入,然后從第一行開始執(zhí)行,把第一個目標test作為它的最終目標,所有后面的目標的更新都會影響到test的更新。第一條規(guī)則說明只要文件test的時間戳比文件prog.o或code.o中的任何一個舊,下一行的編譯命令將會被執(zhí)行。 但是,在檢查文件prog.o和code.o的時間戳之前,make會在下面的行中尋找以prog.o和code.o為目標的規(guī)則,在第三行中找到了關(guān)于prog.o的規(guī)則,該文件的依賴文件是prog.c、prog.h和code.h。同樣,make會在后面的規(guī)則行中繼續(xù)查找這些依賴文件的規(guī)則,如果找不
29、到,則開始檢查這些依賴文件的時間戳,如果這些文件中任何一個的時間戳比prog.o的新,make將執(zhí)行“gcc c prog.c o prog.o”命令,更新prog.o文件。以同樣的方法,接下來對文件code.o做類似的檢查,依賴文件是code.c和code.h。當make執(zhí)行完所有這些套嵌的規(guī)則后,make將處理最頂層的test規(guī)則。如果關(guān)于prog.o和code.o的兩個規(guī)則中的任何一個被執(zhí)行,至少其中一個.o目標文件就會比test新,那么就要執(zhí)行test規(guī)則中的命令,因此make去執(zhí)行g(shù)cc命令將prog.o和code.o連接成目標文件test。在上面Makefile的例子中,還定義了一
30、個目標clean,它是Makefile中常用的一種專用目標,即刪除所有的目標模塊。 現(xiàn)在來看一下make做的工作:首先make按順序讀取makefile中的規(guī)則,然后檢查該規(guī)則中的依賴文件與目標文件的時間戳哪個更新,如果目標文件的時問戳比依賴文件還早,就按規(guī)則中定義的命令更新目標文件。如果該規(guī)則中的依賴文件又是其他規(guī)則中的目標文件,那么依照規(guī)則鏈不斷執(zhí)行這個過程,直到Makefile文件的結(jié)束,至少可以找到一個不是規(guī)則生成的最終依賴文件,獲得此文件的時間戳,然后從下到上依照規(guī)則鏈執(zhí)行目標文件的時間戳比此文件時間戳舊的規(guī)則,直到最頂層的規(guī)則。 通過以上的分析過程,可以看到make的優(yōu)點,因為.o
31、目標文件依賴.c源文件,源碼文件里一個簡單改變都會造成那個文件被重新編譯,并根據(jù)規(guī)則鏈依次由下到上執(zhí)行編譯過程,直到最終的可執(zhí)行文件被重新連接。例如,當改變一個頭文件的時候,由于所有的依賴關(guān)系都在Makefile里,因此不再需要記住依賴此頭文件的所有源碼文件,make可以自動的重新編譯所有那些因依賴這個頭文件而改變了的源碼文件,如果需要,再進行重新連接。 3Makefile中的變量中的變量 Makefile里的變量就像一個環(huán)境變量。事實上,環(huán)境變量在make中也被解釋成make的變量。這些變量對大小寫敏感,一般使用大寫宇母。幾乎可以從任何地方引用定義的變量,變量的主要作用如下: 保存文件名列表
32、。在前面的例子里,作為依賴文件的一些目標文件名出現(xiàn)在可執(zhí)行文件的規(guī)則中,而在這個規(guī)則的命令行里同樣包含這些文件并傳遞給gcc做為命令參數(shù)。如果使用一個變量來保存所有的目標文件名,則可以方便地加入新的目標文件而且不易出錯。 保存可執(zhí)行命令名,如編譯器。在不同的Linux系統(tǒng)中存在著很多相似的編譯器 系統(tǒng),這些系統(tǒng)在某些地方會有細微的差別,如果項目被用在一個非gcc的系統(tǒng) 里,則必須將所有出現(xiàn)編譯器名的地方改成用新的編譯器名。但是如果使用一個變量來代替編譯器名,那么只需要改變該變量的值。其他所有地方的命令名就都改變了。 保存編譯器的參數(shù)。在很多源代碼編譯時,gcc需要很長的參數(shù)選項,在很多情況下,
33、所有的編譯命令使用一組相同的選項,如果把這組選項使用一個變量代表,那么可以把這個變量放在所有引用編譯器的地方。當要改變選項的時候,只需改變一次這個變量的內(nèi)容即可。 Makefile中的變量是用一個文本串在Makefile中定義的,這個文本串就是變量的值。只要在一行的開始寫下這個變量的名字,后面跟一個“”號,以及要設定這個變量的值即可定義變量,下面是定義變量的語法:VARNAME=string使用時,把變量用括號括起來,并在前面加上$符號,就可以引用變量的值: $VARNAME make解釋規(guī)則時,VARNAME在等式右端展開為定義它的字符串。變量一般都在Makefile的頭部定義。按照慣例,所
34、有的Makefile變量都應該是大寫。如果變量的值發(fā)生變化,就只需要在一個地方修改,從而簡化了Makefile的維護。 現(xiàn)在利用變量把前面的Makefile重寫一遍:OBJS=prog.o code.oCC=gcc test:$ OBJS $ CC o test $ OBJS prog.o:prog.c prog.h code.h$ CC c prog.c o prog.o code.o:code.c code.h$ CC c code.c o code.o clean:rm f *.o 除用戶自定義的變量外,make還允許使用環(huán)境變量、自動變量和預定義變量。使用環(huán)境變量的方法很簡單,在mak
35、e啟動時,make讀取系統(tǒng)當前已定義的環(huán)境變量,并且創(chuàng)建與之同名同值的變量,因此用戶可以像在shell中一樣在Makefile中方便的引用環(huán)境變量。需要注意的是,如果用戶在Makefile中定義了同名的變量,用戶自定義變量將覆蓋同名的環(huán)境變量。此外,Makefile中還有一些預定義變量和自動變量,但是看起來并不像自定義變量那樣直觀。表9-3中給出了常見的自動變量。 除了自動變量外,Makefile中還有一些預定義的內(nèi)部變量,用于定義編譯命令名、編譯參數(shù)等,如表9-4所示: 4Makefile的隱含規(guī)則的隱含規(guī)則 在上面的例子中,幾個產(chǎn)生目標文件的命令都是從“.c”的C語言源文件和相關(guān)文件通過編
36、譯產(chǎn)生“.o”目標文件,這也是一般的步驟。實際上,make可以使工作更加自動化,也就是說,make知道一些默認的動作,它有一些稱作隱含規(guī)則的內(nèi)置的規(guī)則,這些規(guī)則告訴make當用戶沒有完整地給出某些命令的時候,應該怎樣執(zhí)行。例如,把生成prog.o和code.o的命令從規(guī)則中刪除,make將會查找隱含規(guī)則,然后會找到并執(zhí)行一個適當?shù)拿?。由于這些命令會使用一些變量,因此可以通過改變這些變量來定制make。象在前面的例子中所定義的那樣,make使用變量CC來定義編譯器,并且傳遞變量CFLAGS(編譯器參數(shù))、CPPFLAGS(C語言預處理器參數(shù))、TARGET_ARCH(目標機器的結(jié)構(gòu)定義)給編譯
37、器,然后加上參數(shù)-c,后面跟變量$(第一個依賴文件名),然后是參數(shù)-o加變量$(目標文件名)。綜上所述,一個C編譯的具體命令將會是:$ CC $ CFLAGS $ CPPFLAGS $ TARGET_ARCH c $ -o $在上面的例子中,利用隱含規(guī)則,可以簡化為:OBJS=prog.o code.oCC=gcctest:$ OBJS $ CC o $ $ prog.o:prog.c prog.h code.hcode.o:code.c code.h clean:rm f *.o 5、常用的、常用的make命令行選項命令行選項 make命令有豐富的命令行選項。表9-5中列出了常用的部分。 9
38、.3.3 使用使用automake和和autoconf產(chǎn)生產(chǎn)生Makefile 在開始使用Automake和autoconf之前,請先確認系統(tǒng)已經(jīng)安裝以下的軟件:GNU AutomakeGNU AutoconfGNU m4Perl GNU Libtool (如果你需要產(chǎn)生 shared library) Automake 所產(chǎn)生的 Makefile 除了可以做到程序的編譯和連接,也已經(jīng)把如何產(chǎn)生程序文件的操作,以及把安裝程序都考慮進去了,所以源程序所存放的目錄架構(gòu)最好符合GNU的標準慣例,下面用hello.c 來作為例子進行說明。 在工作目錄下建立一個新的子目錄devel,再在devel下建立
39、一個hello的子目錄,這個目錄將作為存放 hello 這個程序及其相關(guān)文件的地方: 用編輯器寫個hello.c文件:#include int main(int argc, char* argv) printf(Hello, GNU!n); return 0;接下來就要使用 Autoconf 及 Automake 來產(chǎn)生Makefile文件,步驟如下:(1)autoscan 產(chǎn)生一個configure.in的模板,執(zhí)行 autoscan 后會產(chǎn)生一個configure.scan 的文件,可以用它做為configure.in文件的模板:(2)編輯configure.scan文件,如下所示,并且把
40、文件名改成configure.in (3)執(zhí)行aclocal和autoconf ,分別會產(chǎn)生 aclocal.m4 及 configure 兩個文件:(4)編輯Makefile.am文件,內(nèi)容如下: (5)執(zhí)行automake -add-missing ,Automake 會根據(jù) Makefile.am產(chǎn)生一些文件,包含最重要的Makefile.in: (6)最后執(zhí)行 ./configure :現(xiàn)在你的目錄下已經(jīng)產(chǎn)生了一個Makefile文件,執(zhí)行make命令就可以開始編譯hello.c 成執(zhí)行文件,最后執(zhí)行./hello:# makegcc -DPACKAGE=hello -DVERSION
41、=1.0 -I. -I. -g -O2 -c hello.cgcc -g -O2 -o hello hello.o# ./helloHello! GNU! 9.4 調(diào)試工具調(diào)試工具GDB 9.4.1 GDB調(diào)試器簡介調(diào)試器簡介 Linux系統(tǒng)中包含了GNU 調(diào)試程序gdb,它是一個用來調(diào)試C和 C+ 程序的調(diào)試器??梢允钩绦蜷_發(fā)者在程序運行時觀察程序的內(nèi)部結(jié)構(gòu)和內(nèi)存的使用情況。gdb 所提供的一些功能如下所示:運行程序,設置所有的能影響程序運行的參數(shù)和環(huán)境;控制程序在指定的條件下停止運行; 當程序停止時,可以檢查程序的狀態(tài);修改程序的錯誤,并重新運行程序; 動態(tài)監(jiān)視程序中變量的值; 可以單步執(zhí)
42、行代碼,觀察程序的運行狀態(tài)。 gdb的功能非常強大,到目前為止,gdb已能夠支持Moduls-2、Chill、Pascal和FORTRAN程序的調(diào)試,但是調(diào)試這些語言的源程序時有一些功能還不能使用。例如調(diào)試FORTRAN程序時還不支持表達式的輸入、輸出變量或類FORTRAN的詞法。 gdb程序調(diào)試的對象是可執(zhí)行文件,而不是程序的源代碼文件。然而,并不是所有的可執(zhí)行文件都可以用gdb調(diào)試。如果要讓產(chǎn)生的可執(zhí)行文件可以用來調(diào)試,需在執(zhí)行g(shù)cc指令編譯程序時,加上-g參數(shù),指定程序在編譯時包含調(diào)試信息。調(diào)試信息包含程序里的每個變量的類型和在可執(zhí)行文件里的地址映射以及源代碼的行號。gdb 利用這些信息
43、使源代碼和機器碼相關(guān)聯(lián)。 在命令行上輸入gdb并按回車鍵就可以運行g(shù)db了,如果一切正常的話,將啟動gdb,可以在屏幕上看到以下的內(nèi)容: GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)Copyright 2003 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certa
44、in conditions.Type show copying to see the conditions.There is absolutely no warranty for GDB. Type show warranty for details.This GDB was configured as i386-redhat-linux-gnu.(gdb)啟動gdb后,可以在命令行上指定很多的選項。輸入:help可以獲得gdb的幫助信息。如果想要了解某個具體命令(比如break)的幫助信息,在gdb提示符下輸入下面的命令:break屏幕上會顯示關(guān)于break的幫助信息。從返回的信息可知,br
45、eak是用于設置斷點的命令。另一個獲得gdb幫助的方法是瀏覽gdb的手冊頁。在Linux Shell提示符輸入:man gdb 可以看到man的手冊頁。 9.4.2 GDB命令的基本使用和應用命令的基本使用和應用 1gdb基本命令基本命令 還可以用下面的方式來運行g(shù)db:gdb filename其中,filename是要調(diào)試的可執(zhí)行文件。用這種方式運行g(shù)db可以直接指定想要調(diào)試的程序。這和啟動gdb后執(zhí)行file filename命令效果完全一樣。也可以用gdb去檢查一個因程序異常終止而產(chǎn)生的core文件,或者與一個正在運行的程序相連。 gdb支持很多的命令且能實現(xiàn)不同的功能。這些命令從簡單的
46、文件裝入到允許你檢查所調(diào)用的堆棧內(nèi)容的復雜命令, 下面列出了在使用gdb 調(diào)試時會用到的一些命令。1)file命令:裝入想要調(diào)試的可執(zhí)行文件。 2)cd命令:改變工作目錄。 3)pwd命令:返回當前工作日錄。 4)run命令:執(zhí)行當前被調(diào)試的程序。 5)kill命令:停止正在調(diào)試的應用程序。 6)list命令:列出正在調(diào)試的應用程序的源代碼。 7)break命令:設置斷點。 8)Tbreak命令;設置臨時斷點。它的語法與break相同。區(qū)別在于用tbreak設置的斷點執(zhí)行一次之后立即消失。 9)watch命令:設置監(jiān)視點,監(jiān)視表達式的變化。 10)awatch命令:設置讀寫監(jiān)視點。當要監(jiān)視的表
47、達式被讀或?qū)憰r將應用程序掛起。它的語法與watch命令相同。 11)rwatch命令:設置讀監(jiān)視點,當監(jiān)視表達式被讀時將程序掛起,等侍調(diào)試。此命令的語法與watch相同。 12)next命令:執(zhí)行下一條源代碼,但是不進入函數(shù)內(nèi)部。也就是說,將一條函數(shù)調(diào)用作為一條語句執(zhí)行。執(zhí)行這個命令的前提是已經(jīng)run,開始了代碼的執(zhí)行。 13)step命令:執(zhí)行下一條源代碼,進入函數(shù)內(nèi)部。如果調(diào)用了某個函數(shù),會跳到函數(shù)所在的代碼中等候一步步執(zhí)行。執(zhí)行這個命令的前提是已經(jīng)用run開始執(zhí)行代碼。 14)display命令:在應用程序每次停止運行時顯示表達式的值。15)info break命令:顯示當前斷點列表,包
48、括每個斷點到達的次數(shù)。 16)info files命令:顯示調(diào)試文件的信息。 17)info func命令:顯示所有的函數(shù)名。 18)info local命令:顯示當前函數(shù)的所有局部變量的信息。 19)info prog命令:顯示調(diào)試程序的執(zhí)行狀態(tài)。 20)print命令;顯示表達式的值。 21)delete命令:刪除斷點。指定一個斷點號碼,則刪除指定斷點。不指定參數(shù)則刪除所有的斷點。 22)Shell命令:執(zhí)行Linux Shell命令。 23)make命令:不退出gdb而重新編譯生成可執(zhí)行文件。 24)Quit命令:退出gdb。 2gdb應用實例應用實例 下面使用gdb調(diào)試程序來調(diào)試一個實
49、例。被調(diào)試的程序相當?shù)暮唵? 但展示了gdb的典型應用。下面列出了將被調(diào)試的程序代碼,這個程序被稱為greeting.c , 功能是顯示一個簡單的問候, 再用反序?qū)⑺谐觥?9.5 使用使用RCS/CVS來管理源代碼來管理源代碼 9.5.1 RCS的使用的使用 RCS(Revision Control System)即程序改版控制系統(tǒng),主要功能是用來管理文件的版本,可以節(jié)省空間和時間。這樣就不需要在每個程序開發(fā)到某一個階段就將數(shù)據(jù)拷貝到其他的地方備份起來了。RCS提供了如下幾個最重要的指令的: ci指令:將文件放入RCS目錄下的控制系統(tǒng) co指令:從RCS目錄下將文件取出 rcs指令:用來對R
50、CS文件進行參數(shù)的設置 1基本操作方式基本操作方式 一般而言,RCS所產(chǎn)生出來的文件會放在RCS目錄中。所以第一步必須要在當前的目錄下制作一個文件:rootwyh linux# mkdir RCS接下來只要使用ci指令。就可以把文件備份到RCS改版控制系統(tǒng)中: rootwyh linux# ci test.c 若要將文件取出,可以使用下列指令: rootwyh linux# co test.c 取出來的文件是只讀文件,若要取出可以寫入的工作文件,可以加上-l參數(shù)來鎖定它:rootwyh linux# co -l test.c 此外將文件放入RCS控制系統(tǒng)時,可以使用-l參數(shù)鎖定文件,那么目錄下
51、的文件依然存在: rootwyh linux# ci -l test.c 若要比較當前的文件和RCS中最新版本的文件,可以使用下列指令:rootwyh linux# rcsdiff test.c 2指定版本指定版本 若不指定版本編號時,co會從RCS取得最新的版本。如果要以特定的版本號碼寫入RCS或讀出,可以使用-r參數(shù)選項。rootwyh linux# ci -l -r3.25 test.c-以3.25作為版本編號 rootwyh linux# co -l -r1.2 test.c-將RCS中1.2版的test.c讀出 此外,rcsdiff也可以用來指定任何一個版本和當前程序代碼進行比較。r
52、ootwyh linux# rcsdiff -r3.25 test.c-取出3.25版與test.c進行比較 3關(guān)鍵詞的使用關(guān)鍵詞的使用 在RCS中可以將關(guān)鍵詞變量放入程序代碼中。這些變量經(jīng)過RCS會變成版本的注解。用戶可以將這些關(guān)鍵詞說明當作是程序中的批注。常用的關(guān)鍵詞如下:$Author$:將版本放入RCS的用戶名稱。$Data$:記錄程序代碼放入RCS時的日期和時間。$Header$:記錄文件的標頭,包括RCS路徑名稱、版本號碼、日期、作者等。$ID$:和$Header$相同,但不包括RCS路徑名稱。$Locker$:記錄鎖定本版本的用戶名稱。$Log$:記錄將RCS鎖住的時間,所輸入的
53、文本語句。$RCSfiles$:記錄RCS文件名稱。$Rivision$:指定版本號碼。$Source$:RCS文件名稱,包括其路徑。$State$:使用-s選項所指定的特殊狀態(tài)。 使用關(guān)鍵詞的步驟如下所示:(1)在程序代碼中加入任一關(guān)鍵詞 rootwyh linux#vi test.c (2)將程序代碼放入RCS版本控制系統(tǒng) rootwyh linux# ci -l test.c (3)將文件再次取出。在取出的過程中,co會將每個關(guān)鍵詞展開成其對應的值 rootwyh linux# co -l test.c rootwyh linux# cat test.c 9.5.2 CVS的使用的使用
54、CVS(Concurrent Version System)是個版本控制系統(tǒng),利用該系統(tǒng)可以記錄源代碼文件的歷史。例如,當軟件修改時會產(chǎn)生Bug,并且可能在做這次修改后很長時間不會發(fā)現(xiàn)這些問題。使用CVS就可以容易地回顧老的代碼版本去發(fā)現(xiàn)哪一次的修改導致這些問題。如果CVS保留每一次的代碼版本,會浪費很多的空間。因此CVS使用一種比較聰明的辦法保存多個版本在一個文件中。它僅僅保留版本間的不同內(nèi)容。如果很多人在同一個項目上工作,則CVS使用讓不同開發(fā)者獨立工作的方式解決了這個問題。每一個開發(fā)者的工作都在他自己的目錄內(nèi),并且CVS將在每個開發(fā)者的工作完成后進行合并工作。在Linux下,CVS的使用
55、一般是以命令行方式。通常,CVS有兩種使用方式,一是本機方式,一是遠程執(zhí)行方式。CVS的命令格式是:cvs cvs的選項 cvs的動作 選項 讀者可以用cvs H command列出命令command的使用方法。 1開始項目開始項目 用CVS管理代碼,首先要創(chuàng)建一個“信息倉庫”?!靶畔}庫”簡單來說包含一個目錄結(jié)構(gòu)。它包括要管理的源代碼和用于管理源代碼的各種管理文件。 先設置環(huán)境變量CVSROOT,指向信息倉庫的絕對路徑,然后調(diào)用CVS的init命令:# CVSROOT=/usr/local/cvsroot;export CVSROOT# cvs init # ls -l $CVSROOT 2
56、添加項目的文件、目錄到信息倉庫添加項目的文件、目錄到信息倉庫 要將需要管理的項目的文件加入到信息倉庫,并做上標志。如果從頭開始一個新的項目,就需要創(chuàng)建一個單獨的目錄,并把所有要使用的文件做一個有效的組織。而如果在開始使用源文件之前該目錄就已經(jīng)存在,則只需進入該目錄就行了。然后,就可以輸入源文件目錄: # cvs import -m Create Source Dir cvstest/c wu cvstest 這樣會生成 $CVSROOT/cvstest/c 目錄。 其中-m用來指定注釋信息,如果后面在命令行不指定注釋信息,則會啟動缺省編輯器(vi)要求輸入注釋信息;cvstest/c是項目名稱
57、(實際上是倉庫名,在CVS服務器上會存儲在以這個名字命名的倉庫里);wu, cvstest分別標識了作者和發(fā)行標識。 3命令簡介命令簡介 (1)導出源文件 cvs checkout -r rev-D date-d dir-j merg1 -j merg2 modules -r 導出指定版本的模塊 -D 導出指定日期的模塊 -d 導出指定目錄而不是模塊 -j 合并當前版本和指定版本 使用下面的命令會導出剛才生成的模塊,并在當前目錄下生成與文件倉庫中完全一樣的目錄結(jié)構(gòu): # cvs checkout cvstest/c 對于目錄結(jié)構(gòu)比較復雜的模塊可以在 $CVSROOT/CVSROOT/modul
58、es中加以指定: # cvs checkout CVSROOT/modules 在modules文件中加入下面一行: SOURCE cvstest/c 然后執(zhí)行: # cvs commit m “Add SOURCE” 以后就可以使用下面的命令在當前路徑下生成cvstest/c目錄 # cvs checkout SOURCE 在當前路徑下生成的這個目錄就被稱為工作目錄,對源文件的所有修改都應該在這個目錄下完成,而絕對不允許去改動在文件倉庫中$CVSROOT 目錄下的文件。 (2)刪除、增加、重命名文件和目錄 cvs add -k kflags-m message files. -k 指定以后該
59、文件的缺省導出目錄 -m 對文件的描述 上述命令會加入一個新的文件到文件倉庫里,但直到使用了提交命令它才會真正更新文件倉庫。 cvs remove options files 上述命令會從文件倉庫中刪除文件,但也要到提交之后才有作用。 (3)提交源文件 cvs commit -Rl-m mesg files-R 連子目錄一起提交-l 只提交本地目錄(不提交子目錄)-m 注釋信息在導出源文件之后,在工作目錄中對源文件進行的所有修改都必須在提交之后才能對文件倉庫中的源文件起作用,并且新的文件才能夠被分配一個新的版本號。 (4)釋放工作目錄 cvs release d SOURCE 這個命令會刪除工
60、作目錄 cvstest/c(建議在提交了修改的模塊后執(zhí)行這一步),比使用 rm rf cvstest 要好。 4多用戶開發(fā)多用戶開發(fā) 在多用戶的情況下,如果不同用戶修改的是同一個文件的不同部分,則使用下面的命令就能進行版本合并(把檢出的文件與當前的最新版本合并): # cvs update (1)沖突解決 在有多個用戶對同一個文件進行修改時,如果修改了其中的相同部分,而修改后的內(nèi)容如果有不同的話,出現(xiàn)沖突是不可避免的。如果在CVS 文件倉庫中有一個文件 test.c ,它的版本是1.4,用戶A 先檢出該文件進行修改,而稍后有用戶B檢出該文件進行修改,并提前提交成 1.5,而在用戶A再提交時就會
溫馨提示
- 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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五版電廠煤炭采購合同與環(huán)保型付款策略3篇
- 2025年碳晶片技術(shù)培訓及咨詢合同3篇
- 開發(fā)商繼續(xù)履行合同范本(2篇)
- 工廠員工勞動合同(2篇)
- 二零二五版貨物代理合同范本3篇
- 二零二五年度棉花價格指數(shù)編制與應用合同4篇
- 2025年度個人購房借款合同物業(yè)管理服務協(xié)議3篇
- 二零二五年度中小企業(yè)應收賬款質(zhì)押貸款合同范本4篇
- 2025年航空航天產(chǎn)業(yè)投資入股分紅合同3篇
- 2025年度租賃車輛智能監(jiān)控服務合同遠程管理4篇
- 加強教師隊伍建設教師領(lǐng)域?qū)W習二十屆三中全會精神專題課
- 2024-2025學年人教版數(shù)學七年級上冊期末復習卷(含答案)
- 2025年慢性阻塞性肺疾病全球創(chuàng)議GOLD指南修訂解讀課件
- 2024年上海市中考數(shù)學真題試卷及答案解析
- 2024年全國卷1高考理綜試題及答案
- (完整版)金融市場基礎知識知識點歸納-圖文
- 五年級數(shù)學(小數(shù)乘除法)計算題專項練習及答案
- 小學數(shù)學知識結(jié)構(gòu)化教學
- 2022年睪丸腫瘤診斷治療指南
- 被執(zhí)行人給法院執(zhí)行局寫申請范本
- 飯店管理基礎知識(第三版)中職PPT完整全套教學課件
評論
0/150
提交評論