目錄:
第一章 Linux及Linux編程綜述
第二章 設定開發系統
第三章 使用GNU CC
第四章 使用GNU make 管理項目
第五章 建立可移植的自配置軟體 GNU autoconf
第六章 比較和合并原始碼檔案
第七章 使用RCS和CVS控製版本
第八章 調試
第九章 出錯處理
註:原書639頁,內容繁多,不易快速定位要點。在第一次閱讀過程中,我摘抄要點、記錄心得,形成該筆記,供日後查閱和再學慣用。
說明:$ 表示 終端輸入命令
第一章 Linux及Linux編程綜述
1. Linux不是Unix,Unix是一個註冊商標,需要滿足一大串條款並且支付可觀的費用才能被許可使用
Linux在運行特性上與Unix相似,所有核心代碼都是由Linus和幾位核心駭客手工編寫的。
許多Linux上啟動並執行程式,也是手動編寫的,當然也有移植的
Linux之所以和Unix相像,是因為它遵循POSIX標準
-------------------------------------------------------------------
第二章 設定開發系統第三章 使用GNU CC
1. GCC能編譯ANSI C和傳統C等C語言變體
GCC能編譯C、C++、Objective C
GNU Compiler Collection
2. 增加搜尋路徑 -I <針對標頭檔>
gcc hello.c -I /home/fred/include -o hello
3. 增加搜尋路徑 -L <針對庫檔案>
gcc hello.c -L/home/fred/lib -lnew -o hello
gcc首先在/home/fred/lib 下尋找庫檔案,然後到預設路徑下搜尋
-l 選項使得連結程式使用指定的函數庫中的目標代碼
4. 通常用法
gcc hello.c -L/home/fred/lib -I /home/fred/include -lnew -o hello
告訴GCC連結libnew.so, 在/home/fred/lib 中尋找libnew.so, 以及在/home/fred/include中尋找任何非標準的標頭檔
5. 啟用任何一種調試的選項都會讓二進位檔案的大小急劇增長
6. gcc -c filename 得到目標檔案
第四章 使用GNU make 管理項目
1. make是一種控制編譯或者重複編譯軟體的工具
make可以自動管理軟體編譯的內容、方式和時機,從而使程式員能夠把精力集中在編寫代碼上
2. 為何使用make
(1). 包含多個源檔案的項目在編譯時間都有長而且複雜的命令列
(2). 減少重複編譯所需要的時間。(編譯修改過的部分)
(3). 構建依賴資訊資料庫,檢測是否能找到所需的檔案
(4). 能夠建立一個穩定的編譯環境
(5). 讓編譯過程自動執行
3. makefile
(1). 文本形式的資料庫檔案,包含一些規則告訴make編譯哪些檔案、如何編譯以及在什麼條件下編譯
(2). 規則--三個部分組成
<1>. target : 目標體,即make最終需要建立的東西。
<2>. denpendency: 包含一或多個dependency列表,通常是編譯目標體需要的其它檔案。
<3>. command : 為了從指定依賴建立出目標體所需要執行的命令列表。
target通常是程式,但可以是文字檔、手冊等任何東西。
command可以是編譯器的命令或者shell命令,也可以是任何命令列能完成的命令
(3). 通用形式
target : dependency [denpendency [...]] command command [...]
注意:,每個command的第一個字元必須是 定位字元
4. 一個makefile檔案
sayHelloApp: main.o simple_fun.o simple_fun.hgcc main.o simple_fun.o -o sayHelloApp simple_fun.o: simple_fun.c simple_fun.hgcc -c simple_fun.c main.o: main.cgcc -c main.c .PHONY : clean clean: rm main.o simple_fun.o
5. 偽目標
上面的makefile檔案中的clean並不是對應實際的檔案,是偽目標
偽目標規定了make應該執行的命令
clean沒有依賴體,所以它的命令不會被自動執行,使用make clean
如果不使用.PHONY,如果存在clean的檔案,make就會發現它,
但是使用了.PHONY後,make不檢查是否存在有檔案名稱和依賴體中的一個名字相匹配的檔案,直接執行命令
6. 變數
定義: VARNAME=some_text
使用: $(VARNAME)
除使用者自訂變數外,make運行使用環境變數、自動變數和預定義變數
(1)環境變數: 如果makefile中有同名的,以makefile中的為準
(2)自動變數: make自動用特定的、熟知的值替換。$(@F) : 目標檔案的檔案名稱部分;。。。
(3)預定義變數:用於定義程式名或者給這些程式傳遞標誌和參數。CC : C編譯器;RM :檔案刪除程式;。。。
7. 模式規則
擴充make的隱式規則的一種方法。
類似普通規則,但是它的目標必定有符號“%”,可以任何非Null 字元串匹配。
依賴檔案也必須使用%
8. 注釋
#
9. 命令列
-f file : 指定makefile的檔案名稱
-n : 列印將需要執行的命令,但實際上並不執行這些命令
-s : 在執行時不列印命令名
-w : 如果make在執行時改變目錄,列印目前的目錄名
-d : 列印調試資訊
第五章 建立可移植的自配置軟體 GNU autoconf
1. autoconf
它產生一個能自動設定原始碼包的shell指令碼,以使程式能夠在許多不通品牌的UNIX和類UNIX系統上編譯和運行。
這些指令碼通常名為configure,它們檢查在當前系統中是否提供者所需要的某些功能,在此基礎上產生makefile。
./configure
2. configure.in
為了產生configure指令碼,需要在源檔案樹的根目錄下建立名為configure.in 的檔案。
它調用一系列autoconf宏來測試程式需要的或用到的特性是否存在,以及這些特性的功能。
3. configure.in 檔案的常用格式
AC_INIT #AC_INIT(unique_file_in_source_dir),用來測試目前的目錄是否正確 測試程式 #每個宏一行 測試函數庫 #如果超過一行,需要使用[]和\,[]擴住所有的參數 測試標頭檔 # AC_CHECK_HEADERS([head1.h header2.h \ 測試類型定義 # header3.h]) 測試結構 測試編譯器行為 測試庫函數 測試系統調用AC_OUTPUT #AC_OUTPUT(file) file是空格分割的輸出檔案列表 #用於建立名為makefile或者其它名字的輸出檔案
4. 運行autoscan
autoscan 包含在autoconf軟體包中 (sudo apt-get install autoconf),
是Perl指令碼
從源檔案中抽取與函數調用和標頭檔有關的資訊,並將其輸出到configure.scan 檔案中。
5. config.h.in檔案
包含程式需要的所有#define指令
運行autoconf 內建的名為autoheader的shell指令碼
autoheader通過讀入configure.in、作為autoconf軟體一部分的acconfig.h、
位於原始碼根路徑下用於儲存預先處理符號的acconfig.h(即./acconfig.h) 產生 config.h.in檔案
6. ./acconfig.h
只需要包含可以被autoconf和autoheader讀取和使用的合法定義的C風格預先處理符號
讓宏其作用,則設定其值為1
7. 流程
(1). 編寫源檔案 和 Makefile.in檔案 和 acconfig.h檔案 (2). 運行autoscan 得到configure.scan (3). 重新命名 由configure.scan得到configure.in (4). 運行autoheader 由acconfig.h 和 configure.in 得到 config.h.in (5). 運行autoconf 由configure.in 得到 configure (6). ./configure 由config.h.in 得到 Config.h 由Makefile.in 得到 Makefile (7). 運行make 由makefile 得到 應用程式app
第六章 比較和合并原始碼檔案
1. diff 和 patch 區別
如果認為 diff 是通過從一個檔案中減去另一個檔案來產生者兩個檔案的差別檔案
那麼可以認為 patch 是使用這個差別檔案和其中的源檔案來產生另一個源檔案
2. diff 並排輸出兩個檔案
diff -y -W 80 a.vim b.vim
3. diff3
當兩個人同時修改一個共用檔案時,diff3 就會發揮作用。
它比較兩個人做出的兩套修改內容,建立第3個檔案儲存合并後的輸出結果,並且指出雙方修改的衝突之處。
第七章 使用RCS和CVS控製版本第八章 調試
1. GDB GNU DeBugger
自由軟體聯盟(Free Software Foundation,FSF)的主要軟體工具之一
2. make progname
編寫源檔案main.c
使用make main.c,則輸出cc main.c -o main,並得到main可執行檔
3. gdb 的使用步驟
(1). 使用gcc -g test.c -o test
使用-g 選項,編譯出的可執行代碼才包含調試資訊,否則gdb無法載入改執行檔案
(2). gdb test [core]
core 為可選的檔案,記憶體轉存檔案,增強gdb調試能力
至此進入gdb命令互動介面
4. gdb 常用調試命令
(1). l 查看所載入的檔案
註:gdb 中都可以使用縮減形式:
如 l 代表 list; b 代表 brekpoint; p 代表 print r 代表 run n 代表 next c 代表 continue
(2). b 設定斷點
b 6 在第6行設定斷點 tbreak 6 設定臨時斷點,運行到後就自動移除 ignore 6 忽略斷點6 enable 6 啟用斷點6 disable 6 使斷點6失效
(3). info b 查看斷點
(4). delete 移除斷點
delete 1 移除斷點號為1的斷點
(5). run 運行代碼
預設從代碼首行運行
run 6 從第六行運行
(6). p 查看變數值
p i : 查看變數i 的值
結果顯示:$1 = 2
'$1' 是變數i的標誌
(7). n\s 單步運行
當有函數調用時,s 會進入函數,n 不會進入函數
(8). c 繼續
c : 運行,直到函數結束或者下一個斷點
finish: 運行,直到函數結束
5. gdb 其它常用命令
(1). help
$ help
$ help running
第九章 出錯處理
1. assert
#include <assert.h> void assert(int expression);
如果expression值為假(0),則向stderr列印一條出錯資訊,然後通過函數abort來終止程式運行
2. 如果在
include <assert.h> 之前加上下面的語句
#define NDEBUG
則不會調用assert宏
3. 使用系統日誌
Linux 用兩個守護進程 klogd 和 syslogd 提供了集中的系統日誌功能
syslogd 控制著來自使用者空間程式的訊息的產生。
klogd 供核心和運行在核心空間的程式,特別是裝置驅動程式所使用。
大多數Linux系統,系統日誌位於/var/log 目錄下,包括如:messages,debug,mail,news等等
還可能有其它的日誌,取決於/etc/syslog.conf中定義的日誌功能配置(註:Ubuntu沒有檔案)
標準的控制台日誌守護進程是syslogd,由它來維護這些記錄檔。
寫入系統日誌的訊息由它的層級(level)和功能(facility)來控制,
層級指出了訊息的嚴重性或重要性,而功能告訴維護系統日誌的syslogd守護進程是哪個程式發送的這條訊息
一條日誌訊息的層級和功能合起來被稱為它的優先順序(priority)。
4. syslog的記錄層級
層級 嚴重性 LOG_EMERG 系統不可用 LOG_ALERT 要求立即處理 LOG_CRIT 重大錯誤,比如硬碟故障 LOG_ERR 錯誤條件 LOG_WARNING 警告條件 LOG_NOTICE 正常但重要的訊息 LOG_INFO 純粹的通報訊息 LOG_DEBUG 調試或跟蹤輸出
5. syslog的功能值
功能 訊息源 LOG_AUTHPRIV 私人的安全和授權訊息 LOG_CRON 時鐘守護進程(crond 和 atd) LOG_DAEMON 其它系統守護進程 LOG_KERN 核心訊息 LOG_LOCAL[0-7] 為本地/網站使用而保留 LOG_LPR 列印子系統 LOG_MAIL 郵件子系統 LOG_NEWS 新聞子系統 LOG_SYSLOGsyslog 產生的內部訊息 LOG_USER (預設值)一般使用者級訊息 LOG_UUCP uucp子系統
註:當出現錯誤時,對於使用者級程式來說LOG_WARN已經足夠了
LOG_INFO 對於日常煩人的日誌訊息最合適
LOG_ERR 出現了可能致命的系統錯誤
6. 系統日誌函數
標頭檔 <syslog.h> 定義了syslogd的介面。
建立一個日誌訊息,使用syslog函數,原型為:
#include <syslog.h>void syslog(int priority, char* format,...);
priority 是層級和功能的位邏輯“或”值
format指定寫入日誌的訊息和任何類似printf的格式說明字串
%m 由strerror為errno分配的錯誤訊息 替換
7. 簡單的例子
/*********************************************************** 程式碼 /***********************************************************/#include <stdio.h>#include <syslog.h>int main(int argc,int** argv){//LOG_WARNING 結果寫入 /var/log/syslog 檔案中syslog(LOG_WARNING | LOG_USER,\ "This is a warning from %s,%s %s,%m\n",\ __FILE__,__DATE__,__TIME__); //ubuntu下,LOG_INFO 結果也是寫入 /var/log/syslog 檔案中//LOG_USER是預設的功能級syslog(LOG_INFO,"This is a normal message from %s\n",__FILE__);return 1;} /*********************************************************** 運行結果 /***********************************************************//* 在/var/log/下的syslog檔案中,有如下兩條記錄條記錄:Sep 3 16:39:52 jarvischu-Studio-1435 using_syslog: This is a warning from using_syslog.c,Sep 3 2011 16:39:47,SuccessSep 3 16:39:52 jarvischu-Studio-1435 using_syslog: This is a normal message from using_syslog.c */
8. openlog 定製日誌操作,主要是加上首碼
#include <syslog.h>void openlog(const char *ident, int option, int facility);
ident: 指定加到日誌訊息前的字串
option: 多個選項的位邏輯“或”值
LOG_PID 在每條訊息中包含PID LOG_CONS 如果訊息不能寫入記錄檔,則發送到控制台 LOG_NDELAY 立即開啟連結(預設是在syslog第一次被調用時才開啟連結) LOG_PERROR 把訊息寫入記錄檔的同時也輸出到stderr
facility:即 5. 中的某個值
例:
openlog("JarvisChu",LOG_PID,LOG_USER);syslog(LOG_INFO|LOG_USER,"This is a message\n");
則在/var/log/syslog 檔案中,有如下記錄:
JarvisChu[1231]:This is a message
9. 其它函數
(1). closelog()
如同openlog,可選的,關閉openlog開啟的檔案描述符。
(2). int setlogmask(int priority);
設定所有日誌訊息的預設層級,(即哪些層級的訊息能寫入syslog,哪些不能寫入)
函數返回原來的優先順序
syslog拒絕任何沒有在掩碼中設定的優先順序訊息
同 宏:
LOG_MASK(int priority) :建立僅由一個優先順序組成的掩碼LOG_UPTO(int priority) :建立一個由一系列降序優先順序組成的掩碼
如LOG_UPTO(LOG_NOTICE)建立的掩碼包括了從LOG_EMERG到LOG_NOTICE之間的任何層級的訊息。
而LOG_INFO和LOG_DEBUG層級的訊息則不能通過
待續...
作者:Jarvis Chu
首發:CSDN Blog
轉載請註明出處:http://blog.csdn.net/jarvischu/article/details/6747420