1.引言
linux作業系統在伺服器領域的應用和普及已經有較長的歷史,這源於它的開源特點以及其超越windows的安全性和穩定性。而近年來,linux作業系統在嵌入式系統領域的延伸也可謂是如日中天,許多版本的嵌入式linux系統被開發出來,如uclinux、rtlinux、arm-linux等等。在嵌入式作業系統方面,linux的地位是不容懷疑的,它開源、它包含tcp/ip協議棧、它易整合gui。
鑑於linux作業系統在伺服器和嵌入式系統領域愈來愈廣泛的應用,社會上越來越需要基於linux作業系統進行程式設計的開發人員。
瀏覽許多論壇,經常碰到這樣的提問:「現在是不是很流行unix/linux下的c程式設計?所以想學習一下!但是不知道該從何學起,如何下手!有什麼好的建議嗎?各位高手!哪些書籍比較合適初學者?在深入淺出的過程中應該看哪些不同層次的書?比如好的**、論壇請大家賜教!不慎感激!」
鑑於讀者的需求,在本文中,筆者將對linux平台下c程式設計的幾個方面進行例項講解,並力求回答讀者們關心的問題,以與讀者朋友們進行交流,共同提高。
在本文的**過程中,有任何問題或建議,您可以給筆者傳送email:[email protected]
,您也可以進入筆者的部落格參與討論:
。筆者建議在pc記憶體足夠大的情況下,不要直接安裝linux作業系統,最好把它安裝在執行vmware虛擬機器軟體的windows平台上。
在linux平台下,可用任意乙個文字編輯工具編輯源**,但筆者建議使用emacs軟體,它具備語法高亮、版本控制等附帶功能。
2.gcc編譯器
gcc是linux平台下最重要的開發工具,它是gnu的c和c++編譯器,其基本用法為:
gcc [options] [filenames]
options為編譯選項,gcc總共提供的編譯選項超過100個,但只有少數幾個會被頻繁使用,我們僅對幾個常用選項進行介紹。
假設我們編譯一輸出「hello world」的程式:
/* filename:helloworld.c */
main()
最簡單的編譯方法是不指定任何編譯選項:
gcc helloworld.c
它會為目標程式生成預設的檔名a.out,我們可用-o編譯選項來為將產生的可執行檔案指定乙個檔名來代替a.out。例如,將上述名為helloworld.c的c程式編譯為名叫helloworld的可執行檔案,需要輸入如下命令:
gcc –o helloworld helloworld.c
-c選項告訴gcc僅把源**編譯為目標**而跳過彙編和連線的步驟;
-s 編譯選項告訴gcc 在為 c**產生了組合語言檔案後停止編譯。gcc 產生的組合語言檔案的預設副檔名是.s,上述程式執行如下命令:
gcc –s helloworld.c
將生成helloworld.c的彙編**,使用的是at&t彙編。用emacs開啟彙編**。
-e選項指示編譯器僅對輸入檔案進行預處理。當這個選項被使用時,預處理器的輸出被送到標準輸出(預設為螢幕)而不是儲存在檔案裡。
-o選項告訴gcc對源**進行基本優化從而使得程式執行地更快;而-o2選項告訴gcc產生盡可能小和盡可能快的**。使用-o2選項編譯的速度比使用-o時慢,但產生的**執行速度會更快。
-g選項告訴gcc產生能被gnu偵錯程式使用的除錯資訊以便除錯你的程式,可喜的是,在gcc裡,我們能聯用-g和-o (產生優化**)。
-pg選項告訴gcc在你的程式裡加入額外的**,執行時,產生gprof用的剖析資訊以顯示你的程式的耗時情況。
3.gdb偵錯程式
gcc用於編譯程式,而linux的另乙個gnu工具gdb則用於除錯程式。gdb是乙個用來除錯c和c++程式的強力偵錯程式,我們能通過它進行一系列除錯工作,包括設定斷點、觀查變數、單步等。
其最常用的命令如下:
file:裝入想要除錯的可執行檔案。
kill:終止正在除錯的程式。
list:列表顯示源**。
next:執行一行源**但不進入函式內部。
step:執行一行源**而且進入函式內部。
run:執行當前被除錯的程式
quit:終止gdb
watch:監視乙個變數的值
break:在**裡設定斷點,程式執行到這裡時掛起
make:不退出gdb而重新產生可執行檔案
shell:不離開gdb而執行shell
下面我們來演示怎樣用gdb來除錯乙個求0+1+2+3+…+99的程式:
/* filename:sum.c */
main()
printf("the sum of 1+2+...+ is %d", sum);
}執行如下命令編譯sum.c(加-g選項產生debug資訊):
gcc –g –o sum sum.c
在命令列上鍵入gdb sum並按回車鍵就可以開始除錯sum了,再執行run命令執行sum。
list命令:
list命令用於列出源**,對上述程式兩次執行list,將出現如下畫面(源**被標行號)。
根據列出的源程式,如果我們將斷點設定在第5行,只需在gdb 命令列提示符下鍵入如下命令設定斷點:(gdb) break 5。
這個時候我們再run,程式會停止在第5行。
設定斷點的另一種語法是 break ,它在進入指定函式(function)時停住。
相反的,clear用於清除所有的已定義的斷點,clear 清除設定在函式上的斷點, clear 則清除設定在指定行上的斷點。
watch命令:
watch命令用於觀查變數或表示式的值,我們觀查sum變數只需要執行watch sum。
watch 為表示式(變數)expr設定乙個觀察點,一量表示式值有變化時,程式會停止執行。
要觀查當前設定的watch,可以使用info watchpoints命令。
next、step命令:
next、step用於單步執行,在執行的過程中,被watch變數的變化情況將實時呈現(分別顯示old value和new value)。
next、step命令的區別在於step遇到函式呼叫,會跳轉到到該函式定義的開始行去執行,而next則不進入到函式內部,它把函式呼叫語句當作一條普通語句執行。
4.make
make是所有想在linux系統上程式設計的使用者必須掌握的工具,對於任何稍具規模的程式,我們都會使用到make,幾乎可以說不使用make的程式不具備任何實用價值。
在此,我們有必要解釋編譯和連線的區別。編譯器使用原始碼檔案來產生某種形式的目標檔案(object files),在編譯過程中,外部的符號參考並沒有被解釋或替換(即外部全域性變數和函式並沒有被找到)。因此,在編譯階段所報的錯誤一般都是語法錯誤。而聯結器則用於連線目標檔案和程式包,生成乙個可執行程式。在連線階段,乙個目標檔案中對別的檔案中的符號的參考被解釋,如果有符號不能找到,會報告連線錯誤。
編譯和連線的一般步驟是:第一階段把原始檔乙個乙個的編譯成目標檔案,第二階段把所有的目標檔案加上需要的程式包連線成乙個可執行檔案。這樣的過程很痛苦,我們需要使用大量的gcc命令。
而make則使我們從大量原始檔的編譯和連線工作中解放出來,綜合為一步完成。gnu make的主要工作是讀進乙個文字檔案,稱為makefile。這個檔案記錄了哪些檔案(目的檔案,目的檔案不一定是最後的可執行程式,它可以是任何一種檔案)由哪些檔案(依靠檔案)產生,用什麼命令來產生。make依靠此makefile中的資訊檢查磁碟上的檔案,如果目的檔案的建立或修改時間比它的乙個依靠檔案舊的話,make就執行相應的命令,以便更新目的檔案。
假設我們寫下如下的三個檔案,add.h用於宣告add函式,add.c提供兩個整數相加的函式體,而main.c中呼叫add函式:
/* filename:add.h */
extern int add(int i, int j);
/* filename:add.c */
int add(int i, int j)
C 實驗一 開發環境熟悉及結構化程式設計
實驗名稱 實驗一 開發環境熟悉及結構化程式設計 實驗內容 編寫函式,從鍵盤輸入乙個整數,通過某個函式判斷其是否為質數,並輸出判斷結果。include include using namespace std bool sushu int x return false intmain else retu...
c 程式設計實戰寶典 付強 C 開發實戰寶典pdf
c 開發實戰寶典 內容簡介 本書從初學者的角度講述使用visual studio2008開發環境結合c 語言進行程式開發應該掌握的各項技術,突出 基礎 全面 深入 同時就像書名所暗示的一樣,強調 實戰 效果。在介紹技術的同時,書中都會提供示例或稍大一些的例項,同時在各章的結尾安排有綜合應用,通過幾個...
linux下的C語言開發(網路程式設計)
在開始介紹網路程式設計的方法之前,我們可以回憶一下計算機網路的相關知識。目前為止,我們使用的最多網路協議還是tcp ip網路。通常來說,我們習慣上稱為tcp ip協議棧。至於協議棧分成幾層,有兩種說法。一種是五層,一種是七層,我個人本身也比較傾向於五層的劃分方法。大家可以通過下面的圖看看協議棧是怎麼...