標準 (ANSI C, POSIX, SVID, XPG, ...)
函數庫和系統調用
線上文檔 (man, info, HOW-TO, ...)
C 語言編程風格
庫和標頭檔的儲存位置
共用庫及其相關配置
1.4.1 標準 (ANSI C, POSIX, SVID, XPG, ...)
ANSI C :這一標準是 ANSI(美國國家標準局)於 1989 年制定的 C 語言標準。 後來被 ISO(國際標準組織)接受為標準,因此也稱為 ISO C。
ANSI C 的目標是為各種作業系統上的 C 程式提供可移植性保證,而不僅僅限於 UNIX。 該標準不僅定義了 C 程式設計語言的文法和語義,而且還定義了一個標準庫。這個庫可以根據 標頭檔劃分為 15 個部分,其中包括:
1.字元類型 (ctype.h)、
2.錯誤碼 (errno.h)、
3.浮點常數 (float.h)、
4.數學常數 (math.h)、
5.標準定義 (stddef.h)、
6.標準 I/O (stdio.h)、
7.工具函數 (stdlib.h)、
8.字串操作 (string.h)、
9.時間和日期 (time)、
10.可變參數表 (stdarg.h)、
11.訊號 (signal.h)、
12.非局部跳轉 (setjump.h)、
13.本地資訊 (locale.h)、
14.程式斷言 (assert.h) 等等。
POSIX:該標準最初由 IEEE 開發的標準族,部分已經被 ISO 接受為國際標準。該標準的具體內容 見 1.1.3。POSIX.1 和 POSIX.2 分別定義了 POSIX 相容作業系統的 C 語言系統介面 以及 shell 和工具標準。這兩個標準是通常提到的標準:
SVID:System V 的介面描述。System V 介面描述(SVID)是描述 AT&&;T Unix System V 作業系統的文檔,是對 POSIX 標準的擴充超集。
XPG:X/Open 可移植性指南。X/Open 可移植性指南(由 X/Open Company, Ltd.出版), 是比 POSIX 更為一般的標準。X/Open 擁有 Unix 的著作權,而 XPG 則指定成為 Unix 作業系統必須滿足的要求。
1.4.2 函數庫和系統調用
1. glibc -- GNU 的 C 函數庫
眾所周知,C 語言並沒有為常見的操作,例如輸入/輸出、記憶體管理,字串操作等提供內建的支援。相反,這些功能一般由標準的“函數庫”來提供。GNU 的 C 函數庫,即 glibc,是 Linux 上最重要的函數庫,它定義了 ISO C 標準指定的所有的庫函數,以及由 POSIX 或其他 UNIX 作業系統統變種指定的附加特色,還包括有與GNU系統相關的擴充。目前,流行的 Linux 系統使用 glibc 2.0 以上的版本。glibc 基於如下標準:
1) ISO C:C 程式設計語言的國際標準,即 ANSI C。
2) POSIX:GNU C 函數庫實現了 ISO/IEC 9945-1:1996 (POSIX 系統API, 即 POSIX.1)指定的所有函數。該標準是對 ISO C 的擴充,包括檔案系統介面原語、裝置相關的終端控制函數以及進程式控制制函數。同時,GUN C 函數庫還支援部分由 ISO/IEC 9945-2:1993(POSIX Shell 和 工具標準,即 POSIX.2)指定的函數, 其中包括用於處理Regex和模式比對的函數。
3) Berkeley Unix:BSD 和 SunOS。GNU C函數庫定義了某些UNIX 版本中尚未標準化的函數, 尤其是 4.2 BSD, 4.3 BSD, 4.4 BSD Unix 系統(即"Berkeley Unix")以及"SunOS"(流行的 4.2 BSD 變種,其中包含有某些 Unix System V 的功能). BSD 函數包括 符號連結、select 函數、BSD 訊號處理函數以及通訊端等等。
5) SVID:System V 的介面描述。GNU C 函數庫定義了大多數由 SVID 指定而未被 ISO C 和 POSIX 標準指定的函數。來自 System V 的支援函數包括處理序間通訊和共用記憶體、 hsearch 和drand48 函數族、fmtmsg 以及一些數學函數。
6) XPG:X/Open 可移植性指南。GNU C 函數庫遵循 X/Open 可移植性指南(Issue 4.2) 以及所有的 XSI(X/Open 系統介面)相容系統的擴充,同時也遵循所有的 X/Open Unix 擴充。
2. 其他重要函數庫
除 glibc 之外,流行的 Linux 發行版中還包含有一些其他的函數庫,這些函數庫具有重要地位,例如:
GNU Libtool:GNU Libtool 實際是一個指令碼產生工具,它可以為軟體包開發人員提供一般性 的共用庫支援。
以前,如果原始碼包的開發人員要利用共用庫的優點,則必須為每個軟體包可支援的平台編寫定製的支援代碼。並且還需要設計配置介面,以便軟體包的安裝程式能夠正確選擇要建立的庫類型。利用 GNU Libtool,則可以簡化開發人員的這一工作。它在一個單獨的指令碼中同時封裝了與平台相關的依賴性以及使用者介面。GNU Libtool 可使每個宿主類型的完整功能可通過 一般性的介面獲得,同時為程式員隱藏了宿主的特殊性。GNU Libtool 一致性介面是可靠的, 使用者不必閱讀那些晦澀的文檔,以便在每個平台上建立共用庫。他們只需運行軟體包的配置 指令碼,而由 libtool 完成繁複的工作。
CrackLib:CrackLib 為使用者提供了一個 C 語言函數介面,利用這一函數,可避免使用者選擇容易破解的密碼。該函數庫可在類似 passwd 的程式中使用。
LibGTop:LibGTop 是一個能夠擷取進程資訊以及系統運行資訊的函數庫,這些資訊包括: 系統的一般資訊、SYS V IPC 限制、進程列表、進程資訊、進程映射、檔案系統使用資訊等。
圖形檔案操作函數庫:包括 libungif、libtiff、libpng、Imlib 等,可分別用來操作 GIF、TIFF、PNG 以及其他一些格式圖形檔案。
3. 系統調用
系統調用是作業系統提供給外部程式的介面。在 C 語言中,作業系統的系統調用通常通過函數調用的形式完成,這是因為這些函數封裝了系統調用的細節,將系統調用的入口、參數以及傳回值用 C 語言的函數調用過程實現。在 Linux 系統中,系統調用函數定義在 glibc 中。
談到系統調用時,需要注意如下幾點:
1) 系統調用函數通常在成功時返回 0 值,不成功時返回非零值。如果要檢查失敗原因,則 要判斷 errno 這個全域變數的值,errno 中包含有錯誤碼。 [errno是全域變數!]
2) 許多系統調用的返回資料通常通過引用參數傳遞。這時,需要在函數參數中傳遞一個緩衝區地址,而返回的資料就儲存在該緩衝區中。
不能認為系統調用函數就要比其他函數的執行效率高。要注意,系統調用是一個非常耗時的過程。
有關係統調用我們將在以後詳細講述。
1.4.3 線上文檔 (man, info, HOW-TO, ...)
1. man
man, 即 manunal, 是 UNIX 系統手冊的電子版本。根據習慣,UNIX 系統手冊通常分為不同的部分(或小節,即 section),每個小節闡述不同的系統內容。目前的小節劃分如下:
命令:普通使用者命令
系統調用:核心介面
函數庫調用:普通函數庫中的函數
特殊檔案:/dev 目錄中的特殊檔案
檔案格式和約定:/etc/passwd 等檔案的格式
遊戲。
雜項和約定:標準檔案系統布局、手冊頁結構等雜項內容
系統管理命令。
核心常式:非標準的手冊小節。便於 Linux 核心的開發而包含
其他手冊小節:
l: PostgreSQL 資料庫命令
n: TCL/TK 命令
手冊頁一般儲存在 /usr/man 目錄下,其中每個子目錄(如 man1, man2, ..., manl, mann)包含不同的手冊小節。使用 man 命令查看手冊頁。
man 命令列:
man [-acdfFhkKtwW] [-m system] [-p string] [-C config_file] [-M path] [-P pager] [-S section_list] [section] name
常用命令列:
$ man open
$ man 7 man
$ man ./myman.3
2. info
Linux 中的大多數軟體開發工具都是來自自由軟體基金會的 GNU 項目,這些工具軟體件的線上文檔都以 info 檔案的形式存在。info 程式是 GNU 的超文本協助系統。
info 文檔一般儲存在 /usr/info 目錄下,使用 info 命令查看 info 文檔。
要運行 info,可以在 shell 提示符後輸入 info,也可以在 GNU 的 emacs 中鍵入 Esc-x 後跟 info。
info 協助系統的啟動顯示畫面顯示了一個主題目錄,你可以將游標移動到帶有 * 的主題菜單上面,然後按斷行符號鍵
進入該主題,也可以鍵入 m,後跟主題菜單的名稱而進入該主題。例如,你可以鍵入 m,然後再鍵入 gcc 而進
進入 gcc 主題中。
如果你要在主題之間跳轉,則必須記住如下的幾個命令鍵:
* n:跳轉到該節點的下一個節點;
* p:跳轉到該節點的上一個節點;
* m: 指定菜單名而選擇另外一個節點;
* f:進入交叉引用主題;
* l:進入該視窗中的最後一個節點;
* TAB:跳轉到該視窗的下一個超文本連結;
* RET:進入游標處的超文本連結;
* u:轉到上一級主題;
* d:回到 info 的初始節點目錄;
* h:調出 info 教程;
* q:退出 info。
#DEMO#
3. HOW-TO
可供使用者參考的聯機文檔的另一種形式是 HOWTO 檔案,這些檔案位於系統的 /usr/doc/HOWTO 目錄下。 HOWTO 檔案的檔案名稱都有一個 -HOWTO 尾碼,並且都是文字檔。
每一個 HOWTO 檔案包含 Linux 某一方面的資訊,例如它支援的硬體或如何建立一個引導盤。
要想查看這些檔案,進入 /usr/doc/HOWTO 目錄,使用 more 命令,具體形式如下:
$ cd /usr/doc/HOWTO; more topic-name-HOWTO
另外,HOWTO 文檔還有其他格式的檔案,例如 HTML 和 PS 等,儲存在 /usr/doc/HOWTO/other-formats 下。
4. 其他
Linux 的核心文檔一般包含在核心原始碼中,目錄如下:/usr/src/linux-2.x.x/Documentation
/usr/doc 目錄下包含有大量與特定軟體或函數庫相關的說明性文檔。
1.4.4 C 語言編程風格
編寫這一小節的目的是提醒大家在編程過程中注意編程風格。如果你只是在編寫一些小的練習程式,程式只有一兩百行長的話,編程風格可能並不重要。然而,如果你和許多人一起進行開發工作,或者,你希望在過一段時間之後,還能夠正確理解自己的程式的話,就必須養成良好的編程習慣。在諸多編程習慣當中,編程風格是最重要的一項內容。
良好的編程風格可以在許多方面協助開發人員。如果你閱讀過 Linux 核心原始碼的話,可能會對程式的優美編排所傾倒。良好的編程風格可以增加代碼的可讀性,並協助你理清頭緒。如果程式非常雜亂,大概看一眼就該讓你暈頭轉向了。編程風格最能體現一個程式員的綜合素質。
許多讀者可能對 Windows 所推崇的匈牙利命名法很熟悉。這種方法定義了非常複雜的函數、變數、類型等的命名方法,典型的命名方法是採用大小寫混寫的方式,對於變數名稱,則採用添加首碼的辦法來表示其類型,例如:
char szBuffer[20];
int nCount;
利用 sz 和 n 分別代表字串和整數。為了表示一個變數名稱,採用如下的變數名稱是可能的:
int iThisIsAVeryLongVariable;
在 Linux 中,我們經常看到的是定義非常簡單的函數介面和變數名稱。在 Linux 核心的原始碼中,可以看到 Linux 核心原始碼的編碼風格說明(/ Documentation/CodingStyle)。UNIX 系統的一個特點是設計精巧,並遵守積木式原則。C 語言最初來自 UNIX 作業系統,與 UNIX 的設計原則一樣, C 語言被廣泛認可和使用的一個重要原因是它的靈活性以及簡潔性。因此,在利用 C 語言編寫程式時,始終應當符合其簡潔的設計原則,而不應當使用非常複雜的變數命名方法。Linus 為 Linux 核心定義的 C 語言編碼風格要點如下:
縮排時,使用長度為 8 個字元寬的 Tab 鍵。如果程式的縮排超過 3 級,則應考慮重新設計程式。
大括弧的位置。除函數的定義體外,應當將左大括弧放在行尾,而將右大括弧放在行首。函數的定義體應將左右大括弧放在行首。如下所示:
int function(int x, int y)
{
if (x == y) {
...
} else if (x > y) {
...
} else {
...
}
return 0;
}
應採用簡潔的命名方法。對變數名,不贊成使用大小寫混寫的形式,但鼓勵使用描述性的名稱;儘可能不使用全域變數;不採用匈牙利命名法表示變數的類型;採用短小精悍的名稱表示局部變數;保持函數短小,從而避免使用過多的局部變數。
保持函數短小精悍。
不應過分強調注釋的作用,應盡量採用好的編碼風格而不是添加過多的注釋。
1.4.5 庫和標頭檔的儲存位置
1. 函數庫
/lib:系統必備共用庫
/usr/lib:標準共用庫和靜態庫
/usr/i486-linux-libc5/lib:libc5 相容性函數庫
/usr/X11R6/lib:X11R6 的函數庫
/usr/local/lib:本地函數庫
2. 標頭檔
/usr/include:系統標頭檔
/usr/local/include:本地標頭檔
1.4.6 共用庫及其相關配置
/etc/ld.so.conf:包含共用庫的搜尋位置
ldconfig:共用庫管理工具,一般在更新了共用庫之後要運行該命令
ldd:可查看可執行檔所使用的共用庫