编译和使用APUE的源码
From:http://blog.csdn.net/mitesi/article/details/19015397
APUE說明及源碼下載地址 :http://www.apuebook.com/
APUE 電子版 PDF 下載地址:http://download.csdn.net/download/freeking101/10012610
1. 介紹
總結:APUE是一本經典的書,對于Unix程序員如此,對于其它程序員也是相當有價值的。先給兩張可以概括本書所討論內容的兩張圖片。
第一部分:對本書總體結構的解析
本書共分21章。
? ? ? ? 1-2章為本書的入門簡介與本書的特色所在,為何稱作“特色所在”呢?因為本書始終都是在遵從那3個標準來進行編寫的,即 ISO C、IEEE POSIX、The Single UNIX Specification 這三個標準,每下一行是上一行的超集,對于每一個Unix的c程序員來說都是最重要的編程標準。它決定了你代碼的“高度”與“可用性”。第二章的一節還提到了“limits”即“限制”這個概念,這對于可移植性的代碼很重要。
? ? ? ? 3-5章是關于“文件系統”和相關“I/O函數”的討論,最重要的概念是“文件描述符”。這里面dup 和dup2 函數很值得”嚼味“,有興趣可以看看我的另一篇文章”dup2(fd,0)和dup2(0,fd)一樣嗎?“
? ? ? ? 6章,討論了一些“系統文件”。
? ? ? ? 79章,討論了“進程”。個人認為下面這張圖可以說是對程序的內存布局的典型情況作了很好圖示。(見7.6節)
? ? ? ? 10章,討論了“信號”,它是一種軟中斷。同時,它為“異步通信”的實現提供了可能。
? ? ? ? 11-12章,是相對于《apue》第一版新增的內容之一。對線程作了討論。你可以認為“線程”就是一種特殊的“函數”,只不過它能夠共享調用進程的資源,能夠獨立于調用進程(或其它線程)并行執行。當然線程也可以同步,也可以異步執行。還有很多其它有趣的線程特性,可以詳細地閱讀該書。
13章,討論了“守護進程”的概念與編寫方法。至此,本書的核心內容基本討論完畢。
? ? ? ? 后面14~19章討論了高級I/O,高級進程間通信,及終端和偽終端的概念。
? ? ? ? 14章的高級I/O,主要留意I/O的“阻塞”和“非阻塞”兩種不同形式及各自的應用場合。要特別注意,所謂的阻塞或非阻塞是由“文件”的O_NONBLOCK 標志(注意文件描述符起的作用)決定的,而不是I/O 函數決定的。另外,這個章節中給出了“鎖”的概念,這是進程或線程同步的重要技術。
? ? ? ? 15章討論了進程間通信的種種方法,個人推薦“管道”和“FIFO”兩種,至于“XSI IPC”則不建議使用,理由在書中也說得很清楚。
? ? ? ? 16章討論了“網絡套接字”編程。本想自己畫個圖來說明,沒有時間就以后再說吧。
? ? ? ? 17章討論了基于15章中所討論的“流機制”和16章討論的“套接字”的兩種高級IPC,具體是哪兩個,有興趣自己去看書吧。前者沒有什么可移植性,后者倒是很不錯的概念。(后者很好體現了制定“套接字”的初衷:既可用于網絡的通信,也可用于本機進程的通信)
? ? ? ? 18章討論了終端I/O。(暈!看過才知道,終端的屬性也太多了吧?)
? ? ? ? 19章討論了“偽終端”,即“PTY”的概念和使用它的初衷。個人認為書中已經說得很透徹了。如果你明白了“主設備”和“從設備”的關系,及偽終端運行在從設備上的原理和用處,那么你的知識體系又擴大很多了。
? ? ? ? 20章討論了如何在Unix中構建一個支持 并發訪問的數據庫。
? ? ? ? 21章通過構建一個打印機的CS模型(客戶-服務器)來整合前面大部分章節的知識,做一個應用示例。
第二部分:本書重點內容討論
1.“標準”的重要性。一句話,沒有第一部分所提到的3個標準,就不存在Unix編程了。(個人對“標準”的理解與重視)
2.“內核”是什么?能為我們提供什么功能呢?再回過頭來,看看一開始我給出的兩張圖片。第一張是內核在整個系統中所處的位置,我想說的是:內核是對系統所有硬件資源的“管理和組織者”,你可以說它是“管家”。它負責為上層的軟件運行提供所需的硬件資源的分配和時間調度的分配等等。可以認為內核包含兩大功能:一、驅動程序集合;二、調度系統。第二張是內核所包含的功能模塊,也可以說是本書所討論內容的概括。21個章節中后19個的內容都是對這5個模塊的詳細展開。
3.文件系統的核心概念:“文件描述符”。內核對文件系統的管理都是基于“文件描述符”的。不管是創建文件,移動或復制文件,修改文件,刪除文件都使用“文件描述符”來對某個想操作的文件進行引用和表示。
4.區別一下信號,進程間通信,和進程間同步,及共享等概念的不同。信號,是一種軟中斷;它是異步通信的基礎。所以它(異步通信)是進程間通信的一種方式(我們主要使用的signal調用,kill調用等等)。而進程間通信還有別的形式,如Pipes 即管道(典型的是傳統的無名單工管道),FIFOs(又叫有名管道,典型的是雙工管道),XSI IPC(包括三種:消息隊列,信號量(不是信號的概念哈!),共享內存)。后面這些方式主要是同步通信,它們主要用于進程間同步。而共享,主要是指內存共享,一般會用到14章提到的“鎖機制”來保證一致性,像前面的共享內存就是它的一種應用。但你要知道共享的概念主要有兩方面,一是進程間共享,如“內存共享”,文件共享(dup文件描述符)等;二是線程共享,共享的概念對于線程似乎是“天經地義”的,但主要指的是內存中變量等的“小范圍”共享,這點要與進程共享區別。
5.層次與組件。Unix是一個典型的層次型系統。由第一張圖片可以看出設計者的這種思路。這樣做可以簡化系統的設計,提高系統的性能。另一方面,Unix也是以“組件”(也可叫做“構件”)來將系統的所需功能以模塊的形式很好地組織起來。如圖二。其實,Unix或Linux的內核也是這種思路。比如你可以定制自己所需的高效內核,刪除其中一些不需要的驅動代碼模塊。如果不是這種“組件”的思想,那么為達到定制的目的,你就不得不重寫整個內核了。
6.本書的特色:盡可能給出所有用到的函數原型,以及它的實現思想。作者力求讀者不止能夠全面了解到 Unix 中有哪些你可以用的 龐大的 c 語言庫,更希望能明白我們為何需要某個函數,以及怎樣實現這個函數。Unix中c 語言也是分門別類的,而不是沒有組織的。這種“規范化”的“標準”,給了我很深的印象。(誠如第1條中我強調的那樣)
7.這本書有著所有優秀計算機類書籍的良好組織編排,特別是給出了很詳實的“附錄”和“索引”。這些細節是需要很多時間和功夫才能做到盡善盡美的。這也是國內許多同類書籍缺少的。現在,我可以將它作為“字典”來隨時查閱了。
第三部分:系統地看待編程
該書是一本結合底層的系統級編程參考書。看完之后,對編程有了更加系統級的認識。
早期計算機誕生的目的就是為了解決龐大的計算問題。那時的計算機主要是以“硬件驅動”。
這樣說主要是我認為:用戶把一個計算問題(可以認為是他想運行的程序),通過某種方式,比如打孔紙條輸入給計算機,計算機讀取并分析該程序代碼,做計算,并輸出,比如可以輸出到顯示器上。這種模式,簡單也單調。它不能允許多任務,不能做到更高的硬件資源利用效率。
為了解決效率利用問題,人們希望做一個比較底層的“系統程序”,然后在這個“系統程序”的環境中來組織,管理和調度其他“用戶程序”,從而實現多任務與時間上對硬件資源的更高效利用,即“軟件驅動”硬件資源。從而“操作系統”這個底層軟件誕生了,Unix就是其中一個,而Unix操作系統的核心部分就是“內核”。因為要調度其它多個用戶進程,所以內核要有“調度模塊”,因為這些程序都是要利用計算機的硬件資源來做事情,所以內核要給所有的上層程序提供“驅動模塊”以便它們使用計算機的硬件資源。(見本文第二部分2)
我始終認為軟件和硬件的發展總是緊密關聯的。
現在我們有了“操作系統”,那么現在我們看看這種“軟件驅動”到底給我們帶來了什么好處,與早期的“硬件驅動”比較。
從電腦加電開始,一步步啟動并初始化操作系統(即內核),然后用戶登錄,最后在其中運行自己的計算任務。(見我的另一篇文章:Linux啟動過程,用戶登錄過程,及內核進程調度schedule簡單介紹)schedule(pid=0)就是內核的調度模塊,init(pid=1)就是初始化模塊。在schedule的調度下程序交替利用cpu的時間片完成自己的任務,并受到schedule的調度,如開始,暫停,休眠,終止等等。因為Unix中是“進程樹”的進程組織形式,所以每個程序總有它的父進程,最頂端的父進程就是schedule,所以,內核總是能夠管理和控制其它進程。
用戶將自己的計算任務(可以是某段程序代碼)存儲在內存中供內核調度運行。但是由于內存容量有限,并且易失,所以后來演變為,將程序存放在外存中(比如硬盤),要用時再讀取到內存中供內核調度。怎么有組織的存儲我們的程序還有其他數據文件呢?于是我們需要有一個“文件系統”來管理這些程序和數據文件。而我們想要使用這些文件時,需要一套完善的I/O函數來進行操作,如讀取,修改,寫入等。這些都是本書3~5章和14章所討論內容。
好吧,現在程序已經讀取到了內存中,內核也在某個時間片選中該程序,調度并開始運行它,并賦予它某個pid號和它所需要的種種運行時環境和相關的硬件資源(如內存空間,寄存器,一些文件描述符等等),現在假如它是進程A,它可能由于計算需要還會產生子進程,如進程B來,而系統中可能還有很多其它的進程C,進程D之類的與它可能發生關系。由于Unix是多任務系統。所以在下個時間片,該進程就會被其它進程(比如進程C)替換出cpu,轉而進入暫停或休眠狀態。又由于Unix內核有搶占機制,所以可能當前時間片未完,它也可能被高優先級的其它進程(比如進程D)中斷,被強制替換出cpu。關于進程這一塊就涉及到進程環境的初始化,進程的控制(內核對用戶進程的控制,父進程對子進程的控制等等),由于是多進程環境,所以各個進程之間存在聯系(如父子進程,進程組,會話等概念)。由于多進程之間存在聯系,那么必然需要內核提供一些它們之間相互通信的機制,包括同步通信和異步通信(見本文第二部分4的討論)。這些關于進程的內容都是本書7~9章討論的。而“信號”的機制在10章作了討論,它是異步通信的基礎。15~17章討論了多種Unix下的通信機制。
有人覺得多進程都還不能充分利用計算機的硬件資源,于是就提出了多線程。多線程解決I/O操作對多進程造成阻塞導致效率低的問題。當然多線程還有一些別的特性,一些別的內核線程映射技巧來提高程序的運行效率。這部分在書中11~12章進行了討論。
最后Unix提供了一個其它類別的操作系統少有的東東,即“終端”和“偽終端”的概念和設計。這些“組件”豐富了Unix編程的內容,為程序提供了獨特的終端I/O函數,設計出有用的終端或偽終端程序。本書中18~19章作了深入討論。Linux圖形用戶界面的終端窗口就是一個“偽終端”的前端。
說到圖形界面,這里就再多說幾句,本書中沒有討論這一部分,因為那不是內核所關注的模塊或組件,而是“額外”的組件。如果我們要編寫具有交互功能的程序,那么系統提供圖形界面的“函數庫”就是必須的了。那部分的編程內容你就得另外學習。
一開頭我就說了,這本書不局限于面向Unix程序員,對于其它程序員也會有幫助的。
這里說明一下,比如你是一位Java程序員,那么你能從中學到什么呢。
首先你要知道Java提供了一個“虛擬機”(jvm)的概念,你可以認為它就是一個操作系統,或者內核。
jvm如同內核一樣,提供了自己的庫函數(就像Unix下豐富的底層函數調用一樣)。這些函數庫也有文件I/O函數,進程控制函數,線程控制函數,網絡套接字部分,當然還少不了“信號機制”等等。
知道這些后,你就明白了,在jvm中編程如同在Unix下編程一樣,需要面對的問題也一樣了。
首先你要知道jvm的調度模塊,它提供了那些底層庫函數(驅動模塊),那么你就可以開始編寫代碼了吧。
*****************************************************************************************************
APUE 書中源碼編譯
1.編譯源碼
假設源碼解壓到/home/crazyboy/tmp/apue.2e.src目錄下。首先修改與自己系統對應的Make.defines.*文件,我的是linux系統,就修改Make.defines.linux文件,將里面的WKDIR修改成源碼所在的目錄,即這一行改成"WKDIR=/home/crazyboy/tmp/apue.2e.src".然后make或者make linux。如果make的時候報"ARG_MAX"未定義錯誤,那么修改include目錄下的apue.h文件,添加一行:#define ARG_MAX 4096?然后修改threadctl/getenv1.c和threadctl/getenv3.c這兩個文件,添加#include "apue.h".然后再make
2.使用apue.h和libapue.a
源碼的README中只說明如何編譯,如果要編譯自己敲的代碼的話,需要將include/apue.h拷貝到/usr/include目錄下,再將lib/libapue.a拷貝到/usr/lib/或者/usr/lib64/目錄下.然后就可以在自己敲的代碼中使用#include <apue.h>,編譯的時候需要加上-lapue選項.比如要編譯hello.c:
gcc hello.c -lapue -o hello
確保你已經安裝了gcc和gawk。
?
步驟
1.到www.apuebook.com下載源碼 2.tar解包,cd apue.2e 3.vi Make.defines.linux 修改變量WKDIR,指向你的apue源碼的位置,我的是/home/huangz/code/apue.2e,所以 WKDIR=/home/huangz/code/apue.2e 4.vi include/apue.h 增加一個常量ARG_MAX,這是threadctl/getenv1.c和threadctl/getenv3.c要用到的;4096這個值是參考里給的,如果有問題,自己修改吧。#define ARG_MAX 4096 5.vi threadctl/getenv1.c 增加#include "apue.h" 6.vi threadctl/getenv3.c 增加#include "apue.h" 7.vi threads/badexit2.c 修改第31行,將pthread_self()的返回值轉換為int類型。printf("thread 2: ID is %d\n", (int)pthread_self()); 8.vi std/linux.mk 將兩個nawk改為gawk 9.make 10.sudo cp include/apue.h /usr/includesudo cp lib/libapue.a /usr/lib
好了,測試一下,記得要用-lapue命令讓編譯器鏈接apue庫
gcc main.c -lapue
?
《UNIX?環境高級編程》每個歷程中,都會有這樣一行:?
#include "apue.h"?
這個頭文件是作者把把每個例程中常用的標準頭文件,一些常用的出錯處理函數(err_**()之類的函數)和一些常用的宏定義給整理在一個頭文件中。這個可以省去在每個例程中錄入較多的重復代碼,這樣可以減少每個例程的長度。給讀者帶來了不少麻煩。下面給出一種代碼的編譯方法。
1 、解壓文件到apue.2e目錄
2、修改相應平臺的文件,我使用的是linux,所以修改Make.defines.linux?
你修改的只需要這一行WKDIR=/home/your_dir/apue2e_src/apue.2e,改成自己的目錄路徑
3、cd到apue.2e目錄執行make,之后你會在lib目錄下面找到libapue.a?這個文件.
現在,你可以把它拷貝到你能尋找的地方,在編寫例子的時候,你就可以
4、拷貝apue2e_src/apue.2e/include/apue.h和apue2e_src/apue.2e/lib/libapue.a
到你的代碼目錄。
5、使用gcc -o hello hello.c libapue.a來編譯你的代碼
——————————————————————————————
照著做,然后make一下,最后報錯,大概原因是找不到nawk命令。貌似linux下沒有這命令。查到這命令出現在apue.2e/std/linux.mk文件中,試著把nawk換成gawk,再make clean一下,重新make,編譯通過了。
我使用下面命令編譯源程序:
? gcc -o myls ls1.c -I../include ../lib/libapue.a
——————————————————————————————
gawk命令:
gawk?(?GNU awk?)工具是一種模式掃描和處理語言,它搜索一個或多個文件,以查看這些文件中是否存在匹配指定模式的記錄(通常是文本)。每次發現時,它通過執行動作的方式處理文本。使用?gawk?可以生成報告或者過濾文本,?gawk?的很多結構來自?C?語言。
Gawk?工具是?UNIX awk?的?GNU?版。為了方便起見,很多?linux?系統將?/bin/awk?鏈接到/bin/gawk?,這樣用戶可以使用兩者中的任何一個來運行程序。
/
1.在第二個步驟中要apue.2e中修改Make.defines.linux,但一開始找不到這個文件。原因很簡單:找錯代碼了...重下個。
2.第四個步驟中拷貝?/apue.2e/include/apue.h和/apue.2e/lib/libapue.a到你的代碼目錄。就可以解決找不到源函數的問題。其中/apue.2e下的一大堆fig*就是書中的示例代碼。fig1.3是第一個源碼。
3.在執行#gcc -o test1 fig1.3?libapue.a?編譯時會出現File format not recognized:文件類型顯示不正確的錯誤。只要修改fig1.3名字就OK。
執行命令:#cp fig1.3 sample13.c
#gcc -o test1?sample13.c?libapue.a?就編譯成功了!
目錄
(一) 一起學 Unix 環境高級編程 (APUE) 之 標準IO
(二) 一起學 Unix 環境高級編程 (APUE) 之 文件 IO
(三) 一起學 Unix 環境高級編程 (APUE) 之 文件和目錄
(四) 一起學 Unix 環境高級編程 (APUE) 之 系統數據文件和信息
(五) 一起學 Unix 環境高級編程 (APUE) 之 進程環境
(六) 一起學 Unix 環境高級編程 (APUE) 之 進程控制
(七) 一起學 Unix 環境高級編程 (APUE) 之 進程關系 和 守護進程
(八) 一起學 Unix 環境高級編程 (APUE) 之 信號
(九) 一起學 Unix 環境高級編程 (APUE) 之 線程
(十) 一起學 Unix 環境高級編程 (APUE) 之 線程控制
(十一) 一起學 Unix 環境高級編程 (APUE) 之 高級 IO
(十二) 一起學 Unix 環境高級編程 (APUE) 之 進程間通信(IPC)
(十三) [終篇] 一起學 Unix 環境高級編程 (APUE) 之 網絡 IPC:套接字
總結
以上是生活随笔為你收集整理的编译和使用APUE的源码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用 Python 和 werobot 框
- 下一篇: 安卓逆向_18 --- APK保护策略【