勘誤表

我們將持續追蹤並提供修訂,此頁面提供修正內容,包含:原文更新、語意調整、錯字訂正等。若讀者有問題、建議、或內容、程式碼、實作等有不明瞭的地方,都可來信討論。


 類型 說明影響程度
 更新 遵循原作的資訊更新 
 語意 調整修正語意 
 訂正 修正中文錯字、或原作訂正 
 微調 譯詞一致性微調、編排調整、標點符號、字母大小寫 

【上冊】

依頁次排序
 頁次 類型 修訂內容 修訂日期 版次 提供者
 無頁碼微調保持符號的一致性,在書本開頭的【專家對本書的讚譽】 ,其中第2頁的底部最後一行:

原本是:
-LOÏC DOMAIGNÉ, CHIEF SOFTWARE ARCHITECT (EMBEDDED)CORPULS.COM

將標點符號修改為大寫的逗號:
-LOÏC DOMAIGNÉCHIEF SOFTWARE ARCHITECT (EMBEDDED)CORPULS.COM

 2016/10/29 初版  Jensen Chou 
 無頁碼微調在書本開頭的【專家對本書的讚譽】 ,其中第3頁的第7行: 

原本是:
「一本超水準的書,內含經典珍藏著作 Advanced Programming in the UNIX ...

修改為:
「一本超水準的書,內含經典珍藏著作 Advanced Programming in the UNIX ...

 2016/10/29 初版  Aaron Liao 
 xxix 微調在 Linux 核心與 C 函式庫的版本下方的第二段、第2行:

原本是:
標出與其他 glibc 2.x 版本的差異。

修改為:
出與其他 glibc 2.x 版本的差異。

 2016/10/22 初版 Aaron Liao
 xxxi微調 此頁的倒數第5行中間:

原本是:
...,他不僅熱情投入並鼓勵作者,...

修改為:
...,他熱情投入並鼓勵作者,...

 2016/10/22 初版 Aaron Liao
 xxxii訂正此頁的第2行:

原本是:
終端機、登入記帳、行程群組、作業階段(session)....

修改為:
終端機、登入記帳、行程群組、作業階段(session)....

 2016/10/22 初版 Aaron Liao
 p15微調在此頁的第10行(SUSv3基本規範的第三個部分):

原本是:
Shell 和實用工具(XCU):明確定義了 shell 和各種 UNIX 命令的行為。...

修改為:
Shell 和實用工具(XCU):明確定義了 shell 和各種 UNIX 指令的行為。...

 2016/11/14 初版  Aaron Liao 
 p30    語意此頁中間的符號連結(Symbolic link)第2行開始:

原本是:
在目錄清單中的內容是一個「檔名+指標」的項目,而符號連結則是有特殊標示的檔案,內容是另一個檔案的檔名。(換句話說,一個符號連結在目錄中的內容是「檔名+指標」的一個項目,指標所指向的檔案,其內容 是個字串,此字串是另一個檔案的檔名。)所謂「另一個檔案」通常稱為符號連結的目標(target),通常會說符號連結是「指向」或「參考、參照」目的檔案。在多數情況下,只要在系統呼叫指定了路徑名稱(pathname),核心會自動解參考(dereference)該路徑名稱的每個符號連結,以符號連結所指向的檔案名來替換符號連結。

修改的地方:               
在目錄清單中的內容是一個「檔名+指標」(entry),而符號連結則是一個有特殊標的檔案,內容是另一個檔案的檔名。(換句話說,一個符號連結在目錄中也有一個的內容是「檔名+指標」的一個目,而其指標指向另一個檔案的檔名,檔名是字串格式指標所指向的檔案,其內容 是個字串,此字串是另一個檔案的檔名。)所謂「另一個檔案」通常稱為符號連結的目標(target),通常會說符號連結是「指向」或「參考、參照」到一個目的檔案。在多數情況下,只要在系統呼叫指定了路徑名稱(pathname),核心會自動解參考(dereference,或稱提取)該路徑名稱的每個符號連結,以符號連結所指向的檔名來替換符號連結。

修改後的全文:
在目錄清單中的內容是一個「檔名+指標」條目(entry),而符號連結則是一個有特殊標記的檔案,內容是另一個檔案的檔名。(換句話說,一個符號連結在目錄中也有一個「檔名+指標」的條目,而其指標指向另一個檔案的檔名,檔名是字串格式。)所謂「另一個檔案」通常稱為符號連結的目標(target),通常會說符號連結是「指向」或「參考、參照」到一個目的檔案。在多數情況下,只要在系統呼叫指定了路徑名稱(pathname),核心會自動解參考(dereference,或稱提取)該路徑名稱的每個符號連結,以符號連結所指向的檔名來替換符號連結。


摘要:
簡而言之,這段是要表達,符號連結這類的檔案本身只是指向另一個檔案,但對於目錄中的條目內容而言,符號連結與一般的檔案是相同的。而存取的檔案之路徑名稱中若包含著符號連結,則系統核心會自動解析,將符號連結檔案轉換為連結的對應檔案。


 2016/10/22 初版 Aaron Liao
 p31訂正此頁的第三行,在此行中間的逗點前方,將【檔案】修正為【檔名】。
 2017/07/21 初版 YouChih Wang
 p41微調保持譯詞的一致性,先找出頁面下方的標題 - 2.12 執行緒(Thread),在標題上方的那兩行:

原本是:
(signal mask)中,對其進行阻斷(block)。若訊號在被阻斷時產生,則仍會被擱置,直到它解除阻斷(即從訊號遮罩中移除訊號)。

修改為:
(signal mask)中,對其進行阻塞(block)。若訊號在被阻塞時產生,則仍會被擱置,直到它解除阻塞(即從訊號遮罩中移除訊號)。

 2016/10/24 初版 Aaron Liao
 p44微調保持譯詞的一致性,先找出頁面中間的標題 - 2.17 客戶端/伺服器架構,在此節的第3行:

原本是:
客戶端:向伺服器發送請求息,...

修改為:
客戶端:向伺服器發送請求息,...

 2016/10/24 初版 Aaron Liao
 p47微調第1行:

原本是:
本章涵蓋各式系統程式設計所預先需要的主題。我們先導讀系統呼叫及詳細敘述

修改為: 
本章涵蓋各式系統程式設計所預先需要的主題。我們先簡介系統呼叫及詳細敘述

 2016/10/28 初版 Aaron Liao
 p49微調第1行:

原本是:
系統呼叫編號檢索一張系統呼叫服務常式表格 ...

修改為:
系統呼叫編號檢索一張系統呼叫服務常式表格 ...

 2016/10/28 初版 Aaron Liao
 p51訂正 在 3.2 節的第6行:

原本是:
有些函式庫函式會架構於系統呼叫之上。例如:fopen 函式庫函式實際上是使用open()系統呼叫開啟檔案。

修改為:
有些函式庫函式會架構於系統呼叫之上。例如:fopen() 函式庫函式實際上是使用open()系統呼叫開啟檔案。

 2016/10/28 初版 Aaron Liao
 p52訂正 在中間的 gnu_get_libc_version 函式原型方框往上倒數第2行︰

原本是:
處理這個問題,程式可以在執行期呼叫gnu_get_libc_version()函式,取得可用的 glibc 版本。

修改為:
處理這個問題,程式可以在執行期呼叫gnu_get_libc_version()函式,用以取得可用的 glibc 版本。

 2016/10/28 初版  Aaron Liao 
 p53微調在第2行:

原本是:
UNIX與Linux程式範例之後),但是這個地方不該節省。...

修改為:
UNIX與Linux程式範例之後),但是這個地方不該省略。...

 2016/10/28 初版 Aaron Liao
 p59微調此頁的第1行:

原本是:
函式 fatal() 用在診斷通用錯誤,包含沒有設定errno的函式庫函式錯誤。

修改為:
函式 fatal() 用在診斷通用錯誤,包含函式庫函式沒有設定errno函式庫函式這類錯誤。

 2016/10/28 初版 Aaron Liao
 p73微調在此頁中間的地方:

原本是:
因此,使用下列的結構初始器(initializer)是不可攜的:

修改為:
因此,使用下列的結構初始器(initializer)是不可攜的寫法

 2016/10/28 初版 Aaron Liao
 p73訂正在此頁的最後一段:

原本是:
若我們想要將標準結構的內容寫入檔案,則也須可量標準結構的成員順序。為了可攜性,我們不能直接將結構以二進位整個寫入,而是以特定順序,個別寫入結構欄位(或是以文字格式)。

修改的地方:
若我們想要將標準結構的內容寫入檔案,則也須量標準結構的成員順序。為了可攜性,我們不能直接將結構以二進位整個寫入,而是以特定順序,個別寫入結構欄位寫入(或是使用文字格式)。

修改後的句子:
若我們想要將標準結構的內容寫入檔案,則也須考量標準結構的成員順序。為了可攜性,我們不能直接將結構以二進位整個寫入,而是以特定順序,個別將結構欄位寫入(或是使用文字格式)。

 2016/10/28 初版 Aaron Liao
 p75語意習題3-1:

原本是:
當使用Linux透有的reboot()系統呼叫以重新開啟系統時,第二個參數:magic2必須設定為魔術號碼組(magic number set)的某個數字(如:LINUX_REBOOT_MAGIC2)。這些數字何者最顯著呢?(將它們轉換為十六進位可以得到線索)。

修改的地方: 
當使用Linux有的reboot()系統呼叫重新系統時,第二個參數:magic2必須設定為一組魔術號碼(magic number set)中的某個數字(如:LINUX_REBOOT_MAGIC2)。這些數值的意義為何呢這些數字何者最顯著呢?(將它們轉換為十六進位可以得到線索)。

修改後的句子:
當使用Linux特有的reboot()系統呼叫來重新啟動系統時,第二個參數:magic2必須設定為一組魔術號碼(magic number set)中的某個數字(如:LINUX_REBOOT_MAGIC2)。這些數值的意義為何呢?(將它們轉換為十六進位可以得到線索)。

 2016/10/28 初版 Aaron Liao
 p78微調維持譯詞的一致性,將【返回】修改為【傳回】:

在倒數第2行:

原本是:
write() 呼叫的返回值為 ...

修改為:
write() 呼叫的傳回值為 ...

在倒數第4行:

原本是:
... 則返回值為 0。

修改為:
... 則傳回值為 0。


在倒數第5行:

原本是:
... read() 呼叫的返回值為實際讀取到的位元

修改為:
... read() 呼叫的傳回值為實際讀取到的位元


在倒數第12行:

原本是:
... 並返回

修改為:
... 並傳回

 2016/10/29 初版 Aaron Liao
 p81微調維持譯詞的一致性,將【返回】修改為【傳回】: 

在第2行:

原本是:
其進行解參考,如果呼叫成功,則 open() 將返回一個檔案描述符,...

修改為:
其進行解參考,如果呼叫成功,則 open() 將傳回一個檔案描述符,...


在第3行:

原本是:
函式呼叫中代表該檔案。若發生錯誤,則返回 -1,...

修改為:
函式呼叫中代表該檔案。若發生錯誤,則傳回 -1,...


在表 4-2 下方那一行:

原本是:
15.4 節將詳細描述檔案權限。之後,讀者會瞭解到新建檔案的存取權限不僅依賴 

修改為: 
15.4 節將詳細描述檔案權限。之後,讀者會瞭解到新建檔案的存取權限不僅取決

 2016/10/30 初版 Aaron Liao
 p82微調維持譯詞的一致性,將【返回】修改為【傳回】,在頁面中間的第一個標題: 

原本是:
open() 呼叫所返回的檔案描述符數值
SUSv3規定,如果呼叫 open() 成功,必須保證其返回值為行程中最小的未用檔案描述符

修改為:
open() 呼叫所傳回的檔案描述符數值
SUSv3規定,如果呼叫 open() 成功,必須保證其傳回值為行程中最小的未用檔案描述符

 2016/10/30 初版 Aaron Liao
 p82訂正4.3.1 節標題下方第4行:

原本是:
後一顯示常數的標準化是符合 SUSv3 還是 SUSv4。

修改為: 
後一顯示常數的標準化是符合 SUSv3 還是 SUSv4。

 2016/10/29 初版 Aaron Liao
 p84微調在頁面上方的 O_ASYNC 旗標的第1行:

原本是:
當對於 open() 呼叫所返回的檔案描述符可以進行 I/O 操作時,...

修改為:
 open() 呼叫所回的檔案描述符可以進行 I/O 操作時,...
 
 2016/10/30 初版 Aaron Liao
 p85微調找到 O_DIRECTORY 旗標,在此段落的第1行:

原本是:
如果 pathname 參數並非目錄,則返回錯誤 ...

修改為:
如果 pathname 參數並非目錄,則傳回錯誤 ...

找到 O_DSYNC 旗標:

原本是:
O_DSYNC(自 Linux 2.6.33 版本開始支持

修改為:
O_DSYNC(自 Linux 2.6.33 版本開始提供

找到 O_EXCL 旗標

原本是:
此旗標與 O_CREAT 旗標結合使用表示如果檔案已經存在,則不會開啟檔案,且 open()呼叫失敗,並返回錯誤,錯誤代號errno為EEXIST。換言之,此旗標確保了呼叫者(open( )的呼叫行程)就是建立檔案的行程。檢查檔案存在與否和建立檔案這兩步驟屬於同一原子操作。5.1節將討論原子操作的概念。如果在flags參數中同時指定了O_CREAT和O_EXCL旗標,且pathname參數是符號連結,則open()函式呼叫失敗(錯誤代號errno為EEXIST)。SUSv3之所以如此規定,是要求有特權的應用程式在已知目錄下建立檔案,從而消除了如下安全隱患,使用符號連結開啟檔案會導致在另一位設定建立檔案(例如,系統目錄)。

修改的地方:
此旗標與 O_CREAT 旗標結合使用表示如果檔案已經存在,則不會開啟檔案,且 open()呼叫失敗,並回錯誤,錯誤代號errno為EEXIST。換言之,此旗標確保了呼叫者(open( )的呼叫行程)就是建立檔案的行程。檢查檔案存在與否和建立檔案這兩步驟屬於同一原子操作。5.1節將討論原子操作的概念。如果在 flags 參數中同時指定了O_CREAT和O_EXCL旗標,且pathname參數是符號連結,則open()函式呼叫失敗(錯誤代號errno為EEXIST)。SUSv3之所以如此規定,是為了讓要求有特權的應用程式在已知目錄下建立檔案,從而消除了如下安全隱患,使用符號連結開啟檔案會導致在另一位設定建立檔案而不會因為符號連結而在不同的位置建立檔案(例如,系統目錄)。

修改後的句子:
此旗標與 O_CREAT 旗標結合使用表示:如果檔案已經存在,則不會開啟檔案,且 open()呼叫會失敗,並傳回錯誤,錯誤代號errno為EEXIST。換言之,此旗標確保了呼叫者(open( )的呼叫行程)就是建立檔案的行程。檢查檔案存在與否和建立檔案這兩步驟屬於同一個原子式操作。5.1節將討論原子操作的概念。如果在 flags 參數中同時指定了O_CREAT和O_EXCL旗標,而且pathname參數是符號連結,則open()函式呼叫會失敗(錯誤代號errno為EEXIST)。SUSv3之所以如此規定,是為了讓有特權的應用程式在已知目錄下建立檔案,而不會因為符號連結而在不同的位置建立檔案(例如,系統目錄)。



找到 O_NOATIME 旗標

原本是:
在讀檔案時,不更新檔案的最近存取時間(15.1 節中所描述的st_atime屬性)。要使用該旗標,要麼呼叫行程的有效使用者ID必須與檔案的擁有者相匹配,要麼行程需要擁有特權(CAP_FOWNER)。否則,open()呼叫失敗,並返回錯誤,錯誤代號errnoEPERM

修改為:
在讀檔案時,不更新檔案的最近存取時間(15.1 節中所描述的st_atime屬性)。要使用該旗標,要麼呼叫行程的有效使用者ID必須與檔案的擁有者相匹配,要麼或是行程需要擁有特權(CAP_FOWNER)。否則,open()呼叫失敗,並回錯誤,錯誤代號errnoEPERM

 2016/10/30 初版 Aaron Liao
 p85訂正找到 O_LARGEFILE 旗標,在此段落的第3行:

原本是:
... 此旗標在諸如 Alpha、IA-64 之類的 64  Linux 實作中是無效的。 ...

修改為:
... 此旗標在諸如 Alpha、IA-64 之類的 64 位元 Linux 實作中是無效的。 ...

 2016/10/30 初版 Aaron Liao
 p86微調找到 O_NOFOLLOW 旗標,在此段落的第 3 行:

原本是:
屬於符號連結,則 open() 函式將返回失敗 ...

修改為:
屬於符號連結,則 open() 函式將傳回失敗 ...


找到 4.3.2 標題 open() 呼叫的錯誤,在此段落的第1行:

原本是:
若開啟檔案時發生錯誤,open() 將返回 -1,...

修改為:
若開啟檔案時發生錯誤,open() 將傳回 -1,...

 2016/10/30 初版 Aaron Liao
 p87微調找到 EISDIR 旗標:在此段落的第1行:

原本是:
所指定的檔案屬於目錄,而呼叫者企圖開啟該檔案進行寫入操作。不允許這種用法。

修改為:
所指定的檔案屬於目錄,而呼叫者企圖開啟該檔案進行寫入操作,這是不被允許的用法。

 2016/10/30 初版 Aaron Liao
 p87訂正找到 ENOENT 旗標:

原本是:
檔案不存在,且未指定O_CREAT旗標或指定了 O_CREAT旗標,但pathname參數所指定路徑的某個目錄不存在或者pathname參數為符號連結,而該連結指向的檔案不存在(空連結)。

修改為:
檔案不存在,且未指定O_CREAT旗標或指定了 O_CREAT旗標,但pathname參數所指定路徑的某個目錄不存在,或者pathname參數為符號連結,而該連結指向的檔案不存在(空連結)。

 2016/10/30 初版 Aaron Liao
 p88微調找到標題 4.4 讀取檔案內容:read(),下方的第一行:

原本是:
read() 系統呼叫從檔案描述符 fd 所代表的開啟檔案中讀取資料。

修改為:
read() 系統呼叫從檔案描述符 fd 所代表的開啟檔案中讀取資料。



此頁面的最後一行:

原本是:
而言,這有可能是因為目前讀取位置靠近檔案結尾部。

修改為:
而言,這有可能是因為目前讀取位置靠近檔案結尾


此頁面下列所述的返回都修改為傳回

1. 位於 creat() 函式原型下方的第2行。
2. 位於 read() 函式原型下方的第4行、第6行、第7行、第8行。

 2016/10/30 初版 Aaron Liao
 p89微調找到第 3 行:

原本是:
預設情況下從終端讀取字元,一遇到行符號(\n),read()呼叫就會結束。

修改為:
預設情況下從終端讀取字元,一遇到行符號(\n),read()呼叫就會結束。

在頁面中間的那段文字,此段落的倒數第3行:

原本是:
... 在字串尾部追加代表字串結束的空字元。如果輸入緩衝區的結尾處需要一個表示終止的空字元,必須明確追加
修改為:
... 在字串尾部附加代表字串結束的空字元。如果輸入緩衝區的結尾處需要一個表示終止的空字元,必須明確附加

 2016/10/30 初版 Aaron Liao
 p90微調將位於 write() 函式原型下方第4行的返回修改為傳回

原本是:
如果 write() 呼叫成功,將返回實際寫入檔案的位元組數,該返回值可能小於

修改為:
如果 write() 呼叫成功,將傳回實際寫入檔案的位元組數,該傳回值可能小於


在 close() 函式原型的下方,第二行:

原本是:
明確關閉不再需要的檔案描述符是良好的程式設計習慣,會使程式碼在後續修改時更具可讀性,也更可靠。進而言之,檔案描述符屬於有限資源,因此檔案描述符關閉失敗可能會導致一個行程將檔案描述符資源消耗殆盡。

修改為:
明確關閉不再需要的檔案描述符是良好的程式設計習慣,會使程式碼在後續修改時更具可讀性,也更可靠。進而言之,此外,檔案描述符屬於有限資源,因此若沒有關閉檔案描述符關閉失敗可能,則會導致一個行程將檔案描述符資源消耗殆盡。

 2016/10/30 初版 Aaron Liao
 p92微調在圖 4-1 下方的第4行:

原本是:
如果 whence 參數值為 SEEK_CUR 或 SEEK_END,offset 參數可以為正數也可以為負數;如果 whence 參數值為 SEEK_SET ,offset 參數必須為非負數。

修改為:
如果 whence 參數值為 SEEK_CUR 或 SEEK_END, offset 參數可以為正數也可以為負數;如果 whence 參數值為 SEEK_SET , offset 參數必須為非負數。

 2016/10/30 初版 Aaron Liao
 p93微調
1. 將此頁第1行的返回修改為傳回

2. 找到標題【檔案空洞(file hole)】,並將下方第二行的返回修改為傳回

 2016/10/30 初版 Aaron Liao
 p94微調找到標題【範例程式】,此段落的第四行

原本是:
  • soffset:從檔案開頭檢索到 offset 位元組的位置位設定。

修改為:
  • soffset:從檔案開頭檢索到 offset 位元組的位置位設定

 2016/10/30 初版 Aaron Liao
 p96微調此頁面上方程式碼之下的第1行:

原本是:
下面的 shell 作業階段示範了列表4-3程式的使用,還顯示了從檔案空洞中讀取位元組時的情況:

修改為:
下面的 shell 作業階段示範了列表4-3程式的使用,還顯示了從檔案空洞中讀取一些位元組資料時的情況:

 2016/10/30 初版 Aaron Liao
 p97微調找到標題 4.9 小結,第三段:

原本是:
對於已開啟的每個檔案,核心都會維護一個檔案偏移量,這決定了下一次或寫入操作的起始位置。讀取和寫入操作會隱式修改檔案偏移量。使用lseek()函式可以直接將檔案偏移量設定為檔案中或檔案結尾後的任一位置。在檔案原結尾處之後的某一位置寫入資料將導致檔案空洞。從檔案空洞處讀取檔案將返回內容全0的位元組資料。

修改為:
對於已開啟的每個檔案,核心都會維護一個檔案偏移量,這決定了下一次讀取或寫入操作的起始位置。讀取和寫入操作會隱含地(implicitly)修改檔案偏移量。使用lseek()函式可以直接將檔案偏移量設定為檔案中或檔案結尾後的任一位置。在檔案原結尾處之後的某一位置寫入資料將導致檔案空洞。從檔案空洞處讀取檔案將傳回內容全0的位元組資料。


找到習題 4-2:

原本是:
4.2. 設計一個類似於cp指令的程式,當使用該程式複製一個包含空洞(連續的空位元組)的普通檔案時,要求目的檔案的空洞與原始檔案保持一致。

修改的地方:
4.2. 設計一個類似於cp指令的程式,當使用該程式複製一個包含空洞(連續的空位元組)的普通檔案時,要求也要在目的檔案相對應的位置建立空洞與原始檔案保持一致

修改後的句子:
4.2. 設計一個類似於cp指令的程式,當使用該程式複製一個包含空洞(連續的空位元組)的普通檔案時,也要在目的檔案相對應的位置建立空洞。

 2016/10/30 初版 Aaron Liao
 p103訂正此頁的第7行:

原本是:
述的非原子式循序呼叫,結果一定會如所剛才所說的,造成檔案毀損 ...

修改為:
述的非原子式循序呼叫,結果一定會如剛才所說的,造成檔案毀損 ...

 2016/10/30 初版  Aaron Liao
 p104訂正 此頁中間,大約第14行: 

原本是:
是 O_APPEND、O_NONBLOCK、O-NOATIME、O_ASYNC 與 O_DIRECT。...

修改為:
是 O_APPEND、O_NONBLOCK、O_NOATIME、O_ASYNC 與 O_DIRECT。...

 2016/10/30 初版 Aaron Liao
 p105語意 找到 5.4 節的第 2 行:

原本是:
這些檔案描述符可以在同一個行程或是不同的行程中開啟。

修改為:
這些檔案描述符可能是在同一個行程或是不同的行程中開啟的。


找到 5.4 節的第 8 行:

原本是:
核心為每個行程維護一個開啟檔案描述符表格,此表中的每筆紀錄記載著單一檔案描述符的相關資訊,包含:
  • 一組控制檔案描述符操作的旗標(這種旗標只有一組,即我們在 27.4 節所述的  close-on-exec 旗標)。
  • 一個指向開啟檔案描述符的參考(reference)。
核心維護整個系統的每個開啟檔案描述符表格。(此表有時會參考開啟檔案表,而表格內的紀錄有時稱為 open file handle)。一個開啟檔案描述符會儲存所有與開啟檔案的相關資訊,包含:

修改為:
核心為每個行程維護一個開啟檔案描述符表格,此表中的每筆紀錄記載著單一檔案描述符的相關資訊,包含:
  • 一組控制檔案描述符操作的旗標(這種旗標只有一,即我們在 27.4 節所述的  close-on-exec 旗標)。
  • 一個指向開啟檔案描述符的參考(reference)。
核心維護一張表格,包含整個系統全部每個開啟檔案描述符表格。(此表有時會當作參考開啟檔案表來參考,而表格內的那些紀錄有時稱為 open file handle)。一個開啟檔案描述符會儲存所有與開啟檔案相關資訊,包含:

 2016/10/30 初版 Aaron Liao
 p120訂正 在倒數第 8 行:

原本是:
輸出作為參數。其次,有些程式還將單個「-解釋為表示命令列選項結束的分隔符號。

修改為:
輸出作為參數。其次,有些程式還將單個「-符號解釋為表示命令列選項結束的分隔符號。

 2016/10/30 初版 Aaron Liao
 p121訂正在 mkstemp() 函式原型下方的第7行:

原本是:
通常,開啟暫存檔案不久,程式就會使用 unlink 系統呼叫(參考18.3節)將

修改為:
通常,開啟暫存檔案不久,程式就會使用 unlink() 系統呼叫(參考18.3節)將

 2016/10/30 初版  Aaron Liao 
 p125微調在倒數第六行:

原本是:
檔格式的中介資訊(meta-information)...

修改為:
檔格式的中繼資訊(meta-information)...

 2016/11/04 初版  Aaron Liao 
 p126微調找到6.2節標題,在此段落的第3行: 

原本是:
(20.5節)接受呼叫者用指定的行程 ID 送出訊號給行程。...

修改為:
(20.5節)接受呼叫者將訊號送給行程 ID 所代表的行程。...

 2016/11/04 初版  Aaron Liao 
 p132微調在 6.4 節標題下方,第2行: 

原本是:
因為了解虛擬記憶體有助於後續探討的主題,例如 fork() 系統呼叫、共用記憶體,

修改為:
因為了解虛擬記憶體有助於後續探討的主題,例如 fork() 系統呼叫、共享記憶體,

 2016/11/04 初版  Aaron Liao
 p149微調在第3行後方:

原本是:
程式會崩潰(crash)結束。然而,取決於堆疊的狀態,也可能會引起呼叫與傳回間的無窮呼叫返回迴圈,而程式好像真的從一個目前並未執行的函式中傳回了。

修改的地方:
程式會單純直接當掉(crash)而結束。然而,依據取決於堆疊的狀態,引起呼叫與傳回間的無窮呼叫返回迴圈,也可能會進入無窮的呼叫與返回循環,而程式的行為就像真的從一個目前並未執行的函式中回。

修改後的句子:

程式會單純直接當掉(crash)而結束。然而,依據堆疊的狀態,也可能會進入無窮的呼叫與返回循環,而程式的行為就像真的從一個目前並未執行的函式中返回。

 2016/11/04 初版 Aaron Liao
 p151微調找到中間的標題,在註解段落下方:

原本是:
盡可能避免使用 setjmp(函式和 longjmp() 函式

修改為:
盡可能避免使用 setjmp()函式和 longjmp() 函式
 2016/11/04 初版  Aaron Liao
 p151微調找到 6.9 節的標題,在此段落的第7行:

原本是:
程式呼叫時,命令列參數透過 argc 和 argv 參數提供給 main() 函式。通常, argv[0] 包含呼叫程式的名稱。

修改為:
在執行程式呼叫時,命令列參數透過 argc 和 argv 參數提供給 main() 函式。通常, argv[0] 包含呼叫程式的名稱。

 2016/11/04 初版  Aaron Liao
 p154微調 在 brk()函式原型下方的第二段、第一行:

原本是:
想將 program break 設定為它的初始值底下(如:在&end底下)似乎會導致不可預期的行為,...

修改為:
想將 program break 設定為它的初始值以下(如:在&end以下)似乎會導致不可預期的行為,...

 2016/12/03 初版  Aaron Liao 
 p155微調 在 malloc 函式原型上方那兩行:

原本是:
malloc()函式從堆積配置 size 個位元組(bytes)的記憶體,並傳回一個指向新配置記憶體區塊的指標,不會初始化所配置的記憶體

修改為:
malloc()函式從堆積配置 size 個位元組(bytes)的記憶體,並傳回一個指向新配置記憶體區塊的指標,不會對新配置的記憶體進行初始化


 2016/12/03 初版  Aaron Liao
 p156微調 此頁的第五行:

原本是:
可以最小化程式必須執行sbrk()呼叫的次數(如3.1節所提的,系統呼叫會有小但重要的負荷(overhead)。

修改的地方:
可以最小化程式必須執行sbrk()呼叫的次數減到最少(如3.1節所提的,系統呼叫會有小重要的負荷(overhead)會造成影響的負載)

修改後的句子:
可以將程式必須執行sbrk()呼叫的次數減到最少(如3.1節所述,系統呼叫會有小量但會造成影響的負載)。
 
 2016/12/03 初版  Aaron Liao 
 p164微調 此頁標題【配置對齊的記憶體:memaligh()與posix_memaligh()】的下方: 

原本是:
memalign()與posix_memalign()函式可以從對齊指定的2次方邊界位址開始配置記憶體,對於一些應用程式是有用的功能(例如,參考列表13-1)。

修改為:
設計memalign()與posix_memalign()函式的目的是:可以從一個與2次方邊界對齊的位址開始配置記憶體,對一些應用程式而言是有用的功能(例如,參考列表13-1)。

 2016/12/03 初版  Aaron Liao 
 p174微調找到中間的註解文字(字體較小),在此段落的第5行:

原本是:
念。)類似的同樣適用於 getgrnam() 和 getgrgid() 函式(稍後介紹)。

修改為:
念。)同樣適用於 getgrnam() 和 getgrgid() 函式(稍後介紹)。

 2016/11/04 初版  Aaron Liao 
 p175訂正找到標題【從群組檔檢索紀錄】的下方那一行:

原本是:
函式 getgrnam() 和 getgrgid() 的可從群組檔檢索紀錄。

修改為:
函式 getgrnam() 和 getgrgid() 可從群組檔檢索紀錄。

 2016/11/04 初版  Aaron Liao 
 p179訂正 在 8.5 節的第9行:

原本是:
演算法,表示無法從加密過密碼重新還原為原始的密碼。...

修改為:
演算法,表示無法從加密過密碼重新還原為原始的密碼。...

 2016/11/04 初版 Aaron Liao 
 p181微調修改使語意更清晰,在第三行: 

原本是:
... 將已清除結尾的換行字元且以 NULL 結尾的輸入字串回傳。

修改的地方:
... 將傳回一個輸入字串,已清除此字串結尾的換行字元,並且以 NULL 結尾的輸入字串回傳

修改後的句子:
... 將傳回一個輸入字串,已清除此字串結尾的換行字元,並且以 NULL 結尾。

  2016/11/04 初版  Aaron Liao 
 p187訂正 在此頁的第三段之第四行(不計程式碼)

原本是:
建立一個啟用set-userID(set-group-ID)的程式,用以將行程的有效使用者...

修改為:
建立一個啟用set-user-ID(set-group-ID)的程式,用以將行程的有效使用者...

 2017/01/05 初版  Aaron Liao 
 p205微調在第二行:

原本是:
真實時間(real time):此時間的量測可源自:某個標準點(日曆時間)...

修改為:
真實時間(real time):此時間的量測起點以是源自:某個標準點(日曆時間)...

 2016/11/11 初版 Aaron Liao 
 p207微調在第一行:

原本是:
如果有提供 tz 參數,則會返回一個 timezone 結構,其欄位內容會包含 ...

修改為:
如果有提供 tz 參數,則會傳回一個 timezone 結構,其欄位內容會包含 ...
 
 2016/11/11 初版 Aaron Liao 
 p207微調在 time() 函式原型方框程式碼的下方第四行

原本是:
timep 參數為無效位址時(EFAULT),所以我們通常會以下列的方式進行呼叫(不用錯誤檢查):

修改為:
timep 參數為無效位址時(EFAULT),所以我們通常會以下列的方式進行呼叫(沒有進行錯誤檢查):
 
 2016/11/11 初版 Aaron Liao
 p207語意在標題【 10.2 時間轉換函式】上方的那段註解,這段註解的倒數第二行:

原本是:
gettimeofday() 系統呼叫。此時 time() 系統呼叫的存在就顯得冗贅,所以能以一個 gettimeofday() 函式庫函式來實作

將紅字修改為藍字:
gettimeofday() 系統呼叫。此時 time() 系統呼叫的存在就顯得冗贅,所以也可以將它實作成呼叫 gettimeofday() 的函式庫函式
 
 2016/11/11 初版 Aaron Liao
 p208微調在標題【10.2.1】下方,位於 ctime 函式原型下方的第一行:

原本是:
將指向 time_t 值的指標以 timep 參數代入 ctime() 函式,...

修改為:
將指向 time_t 值的指標值做為 timep 參數代入 ctime() 函式,...


在此頁的最後一個段落,在此段落的第一行:

原本是:
該字串包含一個結尾的換行符號及結尾的空位元組(null byte)。...

修改為:
該字串的結尾包含一個結尾的換行符號及一個結尾的空位元組(null byte)。...


在此頁的最後一行:

原本是:
... 傳回的字串是靜態配置的,之後呼叫 ctime() 時將會覆蓋它。

修改為:
... 傳回的字串是靜態配置的,之後再次呼叫 ctime() 時將會覆蓋這個字串內容

 2016/11/11 初版 Aaron Liao
 p234訂正在本頁的第7行: 

原本是:
sysconf()、pathconf()及fpathconf(),供應用程式呼叫以檢查系統系統的限制和選項。

修改為:
sysconf()、pathconf()及fpathconf(),供應用程式呼叫以檢查系統系統的限制和選項。

 2016/11/13 初版 Aaron Liao
 p234語意在 11.1 系統限制的第3段落(標楷體的小字註解)

原本是:
對於SUSv3定義的限制名稱,說這些包含_MAX字串名稱是最小值是挺令人困惑的。當我們了解這些用來定義某些資源或特性上限值的常數,標準的意思是,此上限值必須有明確的最小值時,這樣就能清楚理解了。
在某些情況,會將限制設定為最大值,而這些值的名稱包含了_MIN字串。這些常數所代表的意思是某些資源的下限,依標準所述,在符合標準的系統中,此下限不能大於某個值。例如,FLT_MIN(1E-37)這個限制的定義是,設定系統中能夠表示的最小浮點數之最大值,且全部遵循標準的系統至少都要能夠表示如此小的浮點數。

整段修改為:
SUSv3所定義的一些限制命名會令人感到混淆,如有些內含_MAX字串的常數,但卻說這些常數是做為最小值用途。標準說資源限制的上限值需有一個最小值,即遵循標準的系統至少要能將該資源限制的上限設定為該常數。
相對地,有些內含_MIN字串的常數可用來指定一些資源或特定的下限。標準說資源限制的下限值不能大於某個特定值。遵循標準的系統至少要能將該資源限制的下限設定為該常數。以FLT_MIN(1E-37)限制為例,這個定義是設定系統所能表示的最小浮點數之最大值,表示遵循標準的系統至少要能設定到這麼小的最小浮點數。

 2016/11/13 初版      Aaron Liao
 p244語意在 11.6 節的第5行中間開始:

原本是:
此外,每個系統可以在編譯期聲明其實作的限制與選項(透過<limits.h><unistd.h>中的常數定義),且(或)在執行期(透過呼叫 sysconf()pathconf()fpathconf()函式)。

修改為: 
此外,每個系統可以在編譯期與(或)在執行期聲明其實作的限制與選項(在編譯期是透過<limits.h><unistd.h>中的常數定義,而在執行期則是透過呼叫 sysconf()pathconf()fpathconf()函式)。

 2016/11/13 初版 Aaron Liao
 p262微調在此頁的倒數第八行:

原本是:
... 檔案的(硬)連結數量、表示檔案最後存取時間、最後修改時間,...

修改一個字:
... 檔案的(硬)連結數量、表示檔案最後存取時間、最後修改時間,...

 
 2016/12/30 初版  Aaron Liao 
 p263微調 在此頁中間 fsync() 函式原型上方的段落:

原本是:
系統呼叫 fsync()會將緩衝資料及開啟檔案描述符 fd 相關的全部中繼資料刷新到磁碟。

增加一個字:
系統呼叫 fsync()會將緩衝資料及開啟檔案描述符 fd 相關的全部中繼資料刷新到磁碟。

在此頁的倒數第二行:

原本是:
...(我們提過檔案中繼資料的改變,如在同步I/O完整性完成狀態,不需要傳輸最後的修改時間。)...

修改為,增加兩個字: 
...(我們提過檔案中繼資料的改變,如在同步I/O完整性資料完成狀態,不需要傳輸最後的修改時間。)...

 2016/12/30 初版  Aaron Liao 
 p264微調 在此頁下方的第一個小字註解段落:

原本是:
若修改過的核心緩衝區在30秒內未顯式同步到磁碟,則一個永久執行的核心執行緒會確保將已修改過的核心緩衝區刷新到磁碟中。此方法可確保緩衝區與其相對應的磁碟檔案不會長時間未同步(因而導致系統崩潰時資料遺失)。在Linux 2.6版本中,此任務由pdflush核心執行緒進行。(在Linux 2.4版本則由kupdated核心執行緒執行。)

修改為:
若修改過的核心緩衝區在30秒內未顯然地(explicitly)同步到磁碟,則一個永久執行的核心執行緒會確保將已修改過的核心緩衝區刷新到磁碟中。此方法可確保緩衝區與其相對應的磁碟檔案不會長時間未同步(因而導致系統崩潰時發生資料遺失)。在Linux 2.6版本中,此任務由pdflush核心執行緒進行。(在Linux 2.4版本則由kupdated核心執行緒執行。)

 
 2016/12/30 初版  Aaron Liao 
 p266微調 在此頁的倒數第三行:

原本是:
圖13-1左方所示的呼叫可在任何時間顯式強制刷新款衝區。

修改為:
圖13-1左方所示的呼叫可在任何時間顯然地強制刷新款衝區。
 
 2016/12/30 初版  Aaron Liao
 p312更新列表15-1的開頭:

原本是:
<#define _BSD_SOURCE     /* Get major() and minor() from <sys/types.h> */
#include <sys/types.h>
#include <sys/stat.h>
將紅字修改為藍字:
#include <sys/sysmacros.h>
#include <sys/stat.h>

 2016/10/19 初版 man7.org
 p349訂正 在標題【16.14小結】下方:

原本是:
Linux從2.6版本之後,開始提供擴充屬性,以允許屬性中繼資料與檔案關聯,格式為一對的命名與值(name-value pair)。

修改為:
Linux從2.6版本之後,開始提供擴充屬性,以允許任意的中繼資料與檔案關聯,格式為一對的命名與值(name-value pair)。

 2016/12/10 初版 Aaron Liao 
 p418微調在此頁的第六行:

原本是:
OR運算後的結果。

修改為
位元OR運算後的結果。


在此頁的最後一行:

原本是:
pathnames相關的監看描述符之「簿記,bookkeeping」資料結構)

修改為:
pathname相關的監看描述符之「簿記,bookkeeping」資料結構)

 2016/11/15 初版  Aaron Liao 
 p420微調在第三段的第三行:

原本是:
inotify_event 結構包含於 read() 傳回的緩衝區中(參考圖19-2)。...

修改為:
inotify_event 結構包含於 read() 傳回的緩衝區中(參考圖19-2)。...

 2016/11/15 初版 Aaron Liao 
 p420語意 在第五段的第二行:

原本是:
read() 中取得多個事件。read() 從 inotify 檔案描述符讀取事件的最小數量與所提供緩衝區中符合的事件數目

修改的地方: 
read() 中取得多個事件。read() 從 inotify 檔案描述符讀取全部的事件數量,若緩衝區空間不足承載,則只會讀取緩衝區能容納的事件數量事件的最小數量與所提供緩衝區中符合的事件數目

修改後的句子:
read() 中取得多個事件。read() 從 inotify 檔案描述符讀取全部的事件數量,若緩衝區空間不足承載,則只會讀取緩衝區能容納的事件數量。

 2016/11/15 初版 Aaron Liao
 p423訂正在第三個段落(此頁中間)

原本是:
接著我們執行指令,在兩個目錄中產生事件,我們先使用 cat(1) 建立檔案:

修正為:
接著我們執行指令,在兩個目錄中產生事件,我們先使用 cat(1) 建立檔案:

 2016/10/21 初版 Aaron Liao
 p442訂正在此頁的第四行:

原本是:
不過我們在許多例程式中依然會在訊號處理常式中呼叫 printf(),...

增加一個字:
不過我們在許多例程式中依然會在訊號處理常式中呼叫 printf(),...

 2017/03/29 初版 Aaron Liao
 p443訂正在此頁的倒數第九行:

原本是:
未規範將呼叫的行程排除在訊號的接收範圍之外,Linux 遵循是 BSD 系統的語意)。

修改為:
未規範將呼叫的行程排除在訊號的接收範圍之外,Linux 遵循 BSD 系統的語意)。

 2017/03/29 初版 Aaron Liao
 p444訂正在此頁的最後一行:

原本是:
另一個角度來看,表示我們可以使用空訊號來檢測指定行程 ID 的行程是否存在。

修改為:
另一個角度來看,表示我們可以使用空訊號來檢測指定行程 ID 所代表的行程是否存在。

 2017/03/29 初版 Aaron Liao
 p459微調在此頁中間的結構型別,需要調整排版:

原本是:

struct sigaction {
    void (*sa_handler)(int);    /* Address of handler */
    sigset_t sa_mask;           /* Signals blocked during handler
invocation */

    int sa_flags;               /* Flags controlling handler invocation */
    void (*sa_restorer)(void);  /* Not for application use */
};

修改為:

struct sigaction {
    void (*sa_handler)(int);    /* Address of handler */
    sigset_t sa_mask;           /* Signals blocked during handler
                                   invocation */

    int sa_flags;               /* Flags controlling handler invocation */
    void (*sa_restorer)(void);  /* Not for application use */
};

 2017/03/29 初版  Aaron Liao 
 p459訂正 此頁的倒數第三行:

原本是:
叫特用途的 sigreturn() 系統呼叫,用以回存行程的執行內文 ...

修改為:
叫特用途的 sigreturn() 系統呼叫,用以回存行程的執行內文 ...


 2017/03/29 初版  Aaron Liao 
 p532微調此頁的倒數第三行: 

原本是:
參數 new_value 的子結構 it_value 可指定計時器到期的延遲時間,...

修改為:
參數 new_value 的子結構 it_value 可指定計時器啟動之後與到期之間的倒數時間,...

 2016/11/14 初版 Aaron Liao 
 p533微調在此頁的第一行中間開始:

原本是:
...,則在計時器每次的到期之後,就會將計時器重置,使得計時器可以在指定的間隔時間之後再次計時倒數

修改為: 
...,則在計時器每次的到期之後,就會依據間隔時間指定的時間值繼續重新倒數計時


在此頁的倒數第六行中間:

原本是:
...,則會在計時器到期時重置。子結構 curr_value.it_interval ...

修改為:
...,則會在計時器到期之後將計時器重置。子結構 curr_value.it_interval ...

 2016/11/14 初版  Aaron Liao 
 p537微調在此頁的標題【較簡單的計時器介面:alarm()】 標題下方的第二行:

原本是:
並且沒有重複的時間間隔(alarm() 以前原本就是設定計時器的 UNIX API。)。

修改為:
而沒有設定要指定重複計時的時間間隔欄位(alarm() 以前原本就是設定計時器的 UNIX API。)。

 2016/11/14 初版  Aaron Liao 
 p538訂正一、將標題【23.3 計時器的排班與準確度】修改為【23.3 計時器的排班與精準度

二、在標題 23.3 計時器的排班與準確度下方,第二段的第二行:

原本是:
計時器的準確(accuracy)往往是受限於軟體時鐘(software clock)的頻率 ...

修改為:
計時器的精準度(accuracy)往往是受限於軟體時鐘(software clock)的頻率 ...
 
 2017/03/13 初版  Aaron Liao 
 p540語意 在頁面上方的程式碼以下的段落,第三行結尾到第四行開頭之處:

原本是:
因此不太常發生,不過這在實務上是可行的技術

修改為:
因此不太可能發生,所以在實務上這項技術還是可行的

 2016/11/14 初版  Aaron Liao 
 p550微調在此頁下方 SIGEV_SIGNAL 旗標段落的第三行中間:

原本是:
... 此結構會傳遞給此訊號的處理常式、...

修改為:
... 此結構會傳遞給此訊號的處理常式、...

 2016/11/14 初版  Aaron Liao 
 p551語意 在 SIGEV_THREAD_ID 旗標的段落中,第二行結尾的地方:

原本是:
SIGEV_SIGNAL 通知會讓訊號在該行程的佇列中排隊,而若行程中有多條執行緒時,則將訊號傳遞給行程中的任一執行緒。請參考33.2節對執行緒互動及訊號的討論。)

修改為:
使用 SIGEV_SIGNAL 通知會讓訊號在該行程的佇列中排隊,而若行程中有多條執行緒時,則會隨意將訊號傳遞給行程中的任一執行緒。請參考33.2節對執行緒互動及訊號的討論。)

找到標題【23.6.2 啟動與停止計時器:timer_settime()】,在標題上方的那個段落:

原本是:
在目前的實作中,核心會為每個以timer_create()建立的POSIX計時器預先配置一個排隊中即時訊號結構,預先配置的目的在於,確保在計時器到期時,至少有一個這樣的結構可供排隊中的訊號使用。這意謂著,可建立的POSIX計時器數量受限於可排隊的即時訊號數量(參考22.8節)。

修改的地方:
在目前的實作中,核心會為每個以timer_create()建立的POSIX計時器預先配置一個排隊即時訊號結構,預先配置的目的在於,確保在計時器到期時,至少有一個這樣的結構可供排隊中的訊號排隊使用。這意謂著,可建立的POSIX計時器數量受限於可排隊的即時訊號的排隊空間數量(參考22.8節)。

修改後的內容:
在目前的實作中,核心會為每個以timer_create()建立的POSIX計時器預先配置一個可排隊的即時訊號結構,預先配置的目的在於,確保在計時器到期時,至少有一個這樣的結構可供訊號排隊。這意謂著,可建立的POSIX計時器數量受限於即時訊號的排隊空間(參考22.8節)。


 2016/11/14 初版  Aaron Liao
 p565微調在標題【範例程式】的上面那一行: 

原本是:
時間到期了,則該檔案描述符表示為可讀。

修改為:
時間到期了,則該檔案描述符表示為(有資料)可讀。

 2016/11/14 初版  Aaron Liao 
 p629微調 在此頁的倒數第三段:

原本是:
函式execvp()和execlp()會在PATH包含的每個目錄中搜尋檔案,從清單開頭的目錄開始,直到成功執行了指定檔案。如果不清楚可執行程式的具體位置,或是不想因以程式寫死(hard-code)而對具體位置產生依賴,則可以利用PATH環境變數的方式。

修改的地方:
函式execvp()和execlp()會在PATH所列包含的每個目錄中搜尋檔案,從清單開頭的目錄開始,直到成功執行了指定檔案為止。如果不清楚可執行程式的具體位置,或是不想因為在程式碼中寫死(hard-code)執行檔位置導致倚賴特定的執行路徑對具體位置產生依賴,則可以利用PATH環境變數的方式達成

修改後的段落:
函式execvp()和execlp()會在PATH所列的每個目錄中搜尋檔案,從清單開頭的目錄開始,直到成功執行了指定的檔案為止。如果不清楚可執行程式的具體位置,或是不想因為在程式碼中寫死(hard-code)執行檔位置而導致倚賴特定的執行路徑,則可以利用PATH環境變數的方式達成。

 2016/12/08初版  Aaron Liao 
 p635微調 在此頁的倒數第三段的第一行:

原本是:
由於awk會把字串longest_line.awk解釋為一個包含無效awk命令的腳本,因而execve()呼叫將以失敗告終

修改為:
由於awk會把字串longest_line.awk解譯為一個包含無效awk指令的腳本,因而execve()呼叫會無法順利完成執行

 2017/01/02初版  Aaron Liao 
 p643微調 在此頁的最後一段:

原本是:
為了收集system()所建立的子行程狀態,以指定的子行程ID呼叫waitpid()。(使用wait()並不合適,因為wait()等待的是任一子行程,因而可能取得其他子行程的狀態。)列表27-8是system()的簡化實作。

修改的地方:
為了收集system()所建立的子行程狀態,我們使用指定的子行程ID呼叫waitpid()(使用wait()並不合適,因為wait()等待的是任子行程,因而可能取得其他子行程的狀態列表27-8是system()的簡化實作。

修改後的段落:
為了收集system()所建立的子行程狀態,我們使用指定的子行程ID來呼叫waitpid()(使用wait()並不合適,因為wait()等待的是任何一個子行程,因而可能取得其他子行程的狀態),列表27-8是system()的簡化實作。
 
 2016/12/08 初版  Aaron Liao 
 p644微調 在列表27-8下方標題之後的第一行:

原本是:
在system()實作的複雜度高,是因為要能正確地處理訊號。

首先需要討論的訊號是SIGCHLD。假設呼叫system()的程式也直接建立了其他子行程,對SIGCHLD的訊號處理常式自身也執行了wait()。

修改的地方:
system()實作之所以複雜度高,是因為要能正確地處理訊號。

首先需要討論的訊號是SIGCHLD。假設呼叫system()的程式也直接建立了其他子行程,並建立了SIGCHLD的訊號處理常式,而且在處理常式中自身也執行了wait()。
 
修改後的段落:
system()實作之所以複雜度高,是因為要能正確地處理訊號。

首先需要討論的訊號是SIGCHLD。假設呼叫system()的程式也直接建立了其他子行程,並建立了SIGCHLD的訊號處理常式,而且在處理常式中執行了wait()。

 2016/12/08 初版  Aaron Liao 
 p662訂正此頁的第四個段落(小字的註解)

原本是:
堆疊的增長方向對架構的依賴是 clone() 設計的一處缺陷。Interl IA-64架構就提供了...

修正為:
堆疊的增長方向需取決於架構的依賴 clone() 設計的一處缺陷。Intel IA-64架構就提供了...



此頁的第五個段落,其中第二行

原本是:
的終止訊號(terminateion signal)...

修正為:
的終止訊號(termination signal)...


 2016/10/19初版  Aaron Liao
 p663微調此頁的第一個段落,其中第二行開頭

原本是:
是在針對執行緒ID以及執行緒區域存放區的使用方面。...

修正為:
是在針對執行緒ID以及執行緒區域儲存空間 (thread-local storage) 的使用方面。...

 2016/10/19 初版 Aaron Liao 
 p663 訂正在此頁的範例程式標題下方,其中第二點

原本是:
若提供命令列參數...

修正為:
提供命令列參數...

  2016/10/19 初版  Aaron Liao
 p672微調在此頁的第二大標題【將子行程的行程 ID 設定為與父行程相同:CLONE_PID(已廢止) 】,此主題的倒數第二行:

原本是:
顆 CPU 建立隱身的空閒行程(idle process)...

修正為:
顆 CPU 建立隱身的閒置行程(idle process)...

 2016/10/29     初版  Aaron Liao
 p692訂正 在此頁的倒數第四行(29.6節),將 pthred_exit() 修正為 pthread_exit()

 2017/03/02 初版  陳勁宇 
 p743微調 在此頁的第一段:

原本是:
一般來說多個執行緒通常會平行執行,每個執行緒各自完成自己的任務,直到呼叫pthread_exit()終止執行緒,或是傳回到呼叫執行緒的函式。

調整的地方:
一般而言,來說多個執行緒通常會平行(parallel)執行,每個執行緒各自完成自己的任務,直到呼叫pthread_exit()終止執行緒為止,或是回到呼叫執行緒的函式。

調整後的結果:
一般而言,多個執行緒通常會平行(parallel)執行,每個執行緒各自完成自己的任務,直到呼叫pthread_exit()終止執行緒為止,或是返回到呼叫執行緒的函式。
 
 2017/01/02 初版  Aaron Liao 
 p749訂正 在中間的函式原型下方的段落:

原本是:
執行緒呼叫函式pthread_cleanup_push()則將routine參數所指定的函式位址新增到清理處理常式堆疊,routine參數是一個函式指標格式如下:

修改為:
執行緒呼叫函式pthread_cleanup_push()則將routine參數所指定的函式位址新增到清理處理常式堆疊,routine參數是一個函式指標,其格式如下:

 2017/01/02 初版  Aaron Liao 
 p750訂正在中間的【範例程式】標題下方的第四行:

原本是:
...,此處理常式在被時會傳入指定於 buf 中的地址做為參數。...

修改的地方:
...,此處理常式在被呼叫時會傳入指定於 buf 中的址做為參數。...

修改後的結果:
...,此處理常式在被呼叫時會傳入指定於 buf 中的位址做為參數。...

 2017/01/02 初版 Aaron Liao


【下冊】

 頁次 類型 修訂內容 修訂日期 版次 提供者
 p774語意第十四行中間開始

原本是:
只有前景行程群組中的行程從讀取控制終端機讀取輸入。當使用者在控制終端機輸入其中一個訊號生成的(signal-generating)終端機字元之後,該訊號會被發送到前景行程群組中的每個成員。

修正為:
只有前景行程群組中的行程可以讀取控制終端機讀取輸入。當使用者在控制終端機輸入其中一個會產生訊號生成的(signal-generating)終端機字元之後,該訊號會被發送到前景行程群組中的每個成員。

 2016/10/01 初版 Aaron Liao
 p911更新 列表40-2的結尾:

原本是:
    printf("%s", ctime((time_t *) &(ut->ut_tv.tv_sec)));
  }
 
  endutxent();
修改為:
    time_t tv_sec = ut->ut_tv.tv_sec;
    printf("%s", ctime((time_t *) &tv_sec));
  }
  endutxent();

 2017/08/26 初版  man7.org 
 p919更新 列表40-4

原本是:
printf("%-8.8s %-6.6s %-20.20s %s", argv[j], llog.ll_line,
                llog.ll_host, ctime((time_t *) &llog.ll_time));
修改為:
time_t ll_time = llog.ll_time;
printf("%-8.8s %-6.6s %-20.20s %s", argv[j], llog.ll_line,
         llog.ll_host, ctime(&ll_time));

 2017/08/26 初版  man7.org
 p954更新列表42-1,從此頁中間的程式碼開始

原本是:
err = dlerror();
    if (err != NULL)
        fatal("dlsym: %s", err);

    /* If the address returned by dlsym() is non-NULL, try calling it
       as a function that takes no arguments */

    if (funcp == NULL)
        printf("%s is NULL\n", argv[2]);
    else
        (*funcp)();

    dlclose(libHandle);                         /* Close the library */

將紅字修改為藍字:

    err = dlerror();
    if (err != NULL)
        fatal("dlsym: %s", err);

    /* Try calling the address returned by dlsym() as a function
       that takes no arguments */

    (*funcp)();

    dlclose(libHandle);                         /* Close the library */

 2016/10/19 初版 man7.org
 p1015更新在此頁的倒數第二段的後半行:

原本是:
在1970年末初次出現在 Columbus UNIX 系統,

修改為:
在1970年代中期,初次出現在 Columbus UNIX 系統,

 2017/06/10初版  man7.org 
 p1024更新在此頁中間,45.4節標題上方的註解文字中(小字體段落)

原本是:
可以對一個IPC物件設定權限,使得擁有者或建立者不能再使用IPC_STAT取得關聯的資料結構(包含物件權限資訊,這表示無法使用45.6節所述的ipcs(1)指令顯示物件),雖然還是可以使用IPC_SET修改物件。

修正為:
可以對一個IPC物件設定權限,使得擁有者或建立者不能再使用IPC_STAT取得關聯的資料結構(包含物件權限資訊,這表示無法使用45.6節所述的ipcs(1)指令顯示物件),雖然還是可以使用IPC_SET修改物件。

 2016/10/19 初版 man7.org
 p1029更新在程式碼下方的第一行

原本是:
在Linux系統上,ipcs(1)只會顯示我們可以讀取的IPC物件資訊,而不管我們是否擁有這些物件。在一些UNIX系統上,ipcs的行為與在Linux的行為相同。然而,有些其它的系統上,ipcs會顯示全部的物件,無論目前使用者是否擁有這些物件的讀取權限。

修正為:
在Linux系統上,ipcs(1)原本只會使用IPC_STAT的ctl操作(45.3節),以便能夠顯示我們可以讀取的IPC物件資訊,而不管我們是否擁有這些物件。在一些UNIX系統上,ipcs的行為與在Linux的行為相同。然而,有些其它的系統上,ipcs會顯示全部的物件,無論目前使用者是否擁有這些物件的讀取權限。最近幾個ipcs版本因為使用了/proc/sysvipc介面的資訊(45.7節),所以可以顯示全部的物件,而不用在乎權限。

 2016/10/19 初版 man7.org
 p1168微調 在表51-1的第一列第三欄,將信號改成號誌 2016/11/28 初版 Aaron Liao 
 p1171微調 在標題【在Linux編譯使用POSIX IPC的程式】 上方的段落,其中的第二行中間:

原本是:
此位元是一個受限的刪除旗標(15.4.5節),設定此位元代表非特權行程只能移除自己的POSIX IPC物件。

修改為:
此位元是用來增設刪除限制的旗標(15.4.5節),設定此位元代表非特權行程只能移除自己的POSIX IPC物件。

 2016/11/28 初版  Aaron Liao
 p1295更新列表57-6,從此頁第一行的程式碼開始

原本是:
    /* Construct well-known address bind socket to it */

    if (remove(SV_SOCK_PATH) == -1 && errno != ENOENT)
        errExit("remove-%s", SV_SOCK_PATH);

    memset(&svaddr, 0, sizeof(struct sockaddr_un));
    svaddr.sun_family = AF_UNIX;
    strncpy(svaddr.sun_path, SV_SOCK_PATH, sizeof(svaddr.sun_path) - 1);
將紅字刪除,並增加藍字:
    /* Construct server socket address bind socket to it */

    if (strlen(SV_SOCK_PATH) > sizeof(svaddr.sun_path) - 1)
        fatal("Server socket path too long: %s", SV_SOCK_PATH);

    if (remove(SV_SOCK_PATH) == -1 && errno != ENOENT)
        errExit("remove-%s", SV_SOCK_PATH);

    memset(&svaddr, 0, sizeof(struct sockaddr_un));
    svaddr.sun_family = AF_UNIX;
    strncpy(svaddr.sun_path, SV_SOCK_PATH, sizeof(svaddr.sun_path) - 1);
 2016/10/19 初版 man7.org
 p1299語意在列表57-8中,程式碼的第五行之註解:

    str = "xyz";              /* Abstract name is "\0abc" */
        
將 abc 修改為 xyz:

    str = "xyz";              /* Abstract name is "\0xyz" */
 2017/08/28 初版 Chase Lin
 p1344微調 在標題【伺服器程式】下方的第一點:

原本是:
將伺服器的序號初始化為0,或是設定為(選配的)命令列參數①所提供的值。

修改為:
將伺服器的序號(sequence number,又稱流水號)初始化為0,或是設定為(選配的)命令列參數①所提供的值。

在第二點:

原本是:
忽略 SIGPIPE 訊號②,這可以避免伺服器在嘗試寫入對方已關閉的 socket 時,收到 SIGPIPE 訊號;而是在 write() 失敗時出現 EPIPE 錯誤。

修改為:
忽略 SIGPIPE 訊號②,這個步驟的目的是:若伺服器試圖對彼端已關閉的 socket 進行寫入時,不會收到 SIGPIPE 訊號,而只是 write() 失敗並出現 EPIPE 錯誤。

 2017/06/17 初版  Aaron Liao
 p1345微調 在此頁的第一行:

原本是:
- 透過將 reqLen 新增到 seqNum 以更新伺服器的序號值⑮。

修改為:
- 更新伺服器序號值⑮的方式是將 reqLen 數值加到 seqNum 中。
 
 2017/06/17 初版  Aaron Liao 
 p1360訂正在標題 59.14 上方的段落:

原本是:
函式 getservbyport() 函式的功能與 getservbyname() 功能相反,它會傳回一筆取自 /etc/services 的 servent 紀錄,其埠號匹配符合 port 且其通訊協定匹配符合 proto。接著,我們將 proto 設定為 NULL,在此例中,該呼叫可傳回其埠號可匹配符合 port 的紀錄。(在少數情況下,這不會傳回傳回所需的結果,當 TCP 與 UDP 是相同的埠號,但對應到不同的服務名稱時若同一個埠號在 TCP 與 UDP 是分別對應到不同的服務時,在前述所介紹的情況中可能不會傳回所需的結果)。

修改為:
getservbyport() 函式的功能與 getservbyname() 功能相反,它會傳回一筆取自 /etc/services 的 servent 紀錄,其埠號匹配 port 且其通訊協定匹配 proto。接著,我們將 proto 設定為 NULL,在此例中,該呼叫可傳回其埠號可匹配 port 的紀錄。(若同一個埠號在 TCP 與 UDP 是分別對應到不同的服務時,在前述所介紹的情況中可能不會傳回所需的結果)。

 2017/06/17  初版  Aaron Liao
 p1361訂正 在此頁的第二點:

原本是:
我們可以使用資料夾(在 Linux 還可以使用檔案)的權限,來控制存取 UNIX domain socket,以便只有指定的使用者或群組 ID 應用程式可以連線到監聽式 stream socket、或傳送 datagram 到 datagram socket 的應用程式。...

修改為:
我們可以使用資料夾(在 Linux 還可以使用檔案)的權限,來控制存取 UNIX domain socket,以便只有特定使用者或群組 ID 的應用程式可以連線到監聽式 stream socket、或傳送 datagram 到 datagram socket 的應用程式。...

 2017/06/17 初版  Aaron Liao 
 p1443更新在此標題以下【MIN > 0,TIME > 0(既具備超時機制,又有最小讀取位元組數的要求)】,在其第二段第二行處:

原本是:
例如,許多終端機的左方向鍵會產生一個3字元序列,由(escape 與 OD 組成)

修改為:
例如,許多終端機的左方向鍵會產生一個3字元序列(一個 Escape 後面接著 [D 字元)

 2017/06/10 初版 man7.org
 p1466微調 在此頁的第六行後面開始:

原本是:
如果我們針對一個檔案描述符進行大量的 I/O,那麼問題在於可能會引發其他注意的檔案描述符發生飢餓(starve)。

修改的地方:
如果我們針對一個檔案描述符進行大量的 I/O,那麼問題在於可能會引發造成我們關注的其他注意的檔案描述符發生飢餓(starve)的問題

修改後的句子:
如果我們針對一個檔案描述符進行大量的 I/O,那麼可能會造成我們關注的其他檔案描述符發生飢餓(starve)的問題。
 
 2016/11/18 初版  Aaron Liao 
 p1469微調 在此頁的第二段(即註解下方那一段),此段落的倒數第二行:

原本是:
... (因為若我們在迴圈中重複呼叫 select(),select() 會修改這些結構,我們必須確保對他們重新初始化)...

修改的地方:
... (因為若我們迴圈重複呼叫 select(), select() 會修改這些結構,所以我們必須在重新呼叫之前再次初始化這些結構確保對他們重新初始化)... 

修改後的句子:
... (因為若我們以迴圈重複呼叫 select(),則 select() 會修改這些結構,所以必須在重新呼叫之前再次初始化這些結構)...


在此頁的第四段,第二行:

原本是:
對於 nfds 參數的設定,要找出三個檔案描述符集內最大的檔案描述符數值,

修改為:
對於 nfds 參數的設定,要找出三個檔案描述符集內最大的檔案描述符數值,

 2016/11/20 初版  Aaron Liao 
 p1469語意 在此頁的倒數第二段,第一行:

原本是:
雖然 timeval 結構提供微秒的精度,而這個呼叫的精度受限於軟體時脈的粒度(granularity)(10.6節)。SUSv3對 timeout的規範為無條件進位,若它沒有剛好為粒度的倍數時。

修改為的地方:
雖然 timeval 結構提供微秒的精度,而這個呼叫的精度受限於軟體時脈的粒度(granularity)(10.6節)。SUSv3對 timeout的規範為將它延展為粒度的倍數無條件進位,若它沒有剛好為粒度的倍數時

修改後的句子:
雖然 timeval 結構提供微秒的精密度,而這個呼叫的精準度受限於軟體時脈的粒度(granularity)(10.6節)。SUSv3對 timeout的規範為將它延展為粒度的倍數。

 2017/03/02 初版 Aaron Liao 
 p1470微調 在此頁的第六行(即註解段落的第一行):

原本是:
較早的UNIX平台沒有小於一秒的睡眠呼叫(如:nanosleep()),...

修改為:
較早的UNIX平台缺乏精密度少於沒有小於一秒的睡眠呼叫(如:nanosleep()),...


在註解段落下方那一個段落的倒數第二行:

原本是:
確定每次呼叫 select() 以前都要先初始化 timeout 所指的資料結構,並忽略呼叫結束後所傳回的結構內容資訊。

修改為:
確定每次呼叫 select() 以前都要先初始化 timeout 所指的資料結構,並忽略在這次呼叫結束後所傳回的結構內容資訊。


在此頁的標題【select() 的傳回值】下方的第一個項目之第二行:

原本是:
readfds、writefds 或 exceptfds 中的檔案描述符之一是無效的(如:現在還沒開啟)。

修改為:
readfds、writefds 或 exceptfds 中的某個檔案描述符之一是無效的(如:現在還沒開啟)。

 2016/11/20  初版  Aaron Liao 
 p1476微調 在【timeout 參數】標題底下的最後一段:

原本是:
當使用 select() 時,timeout的精準度受限於軟體時脈的區間(10.6節),而 SUSv3 規範 timeout 總是無條件進位,若它不是剛好為時脈區間的倍數時。

修改的地方:
當使用 select() 時,timeout的
精準度受限於軟體時脈的粒度區間(10.6節),而SUSv3規範,timeout 並非總是無條件進位,若它不是剛好為時脈粒度區間的倍數時,則總會被延展以對齊倍數

修改後的句子:
當使用 select() 時,timeout的
精準度受限於軟體時脈的粒度(10.6節),而SUSv3規範若timeout 並非剛好為時脈粒度的倍數時,則總會被延展以對齊倍數。

 2017/03/02 初版  Aaron Liao 
 p1478訂正 在此頁的標題【63.2.3 檔案描述符何時就緒?】下方的段落之第二行:

原本是:
SUSv3 談到,若是一個 I/O 函式呼叫不會發生阻塞,不管函式是否真的傳送資料,就會將一個檔案描述符(明確指定 O_NONBLOCK)認定為就緒。斜體字是關鍵處:...

修改的地方:
SUSv3 談到,若是一個 I/O 函式呼叫不會發生阻塞,不管函式是否真的傳送資料會將一個(有明確指定 O_NONBLOCK 的)檔案描述符(明確指定 O_NONBLOCK)認定為就緒。體字是關鍵處:...

修改後的句子:
SUSv3 談到,若是一個 I/O 函式呼叫不會發生阻塞,則不管函式是否真的傳送資料,都會將一個(有明確指定 O_NONBLOCK 的)檔案描述符認定為就緒。粗體字是關鍵處:...

 2016/11/20 初版  Aaron Liao 
 p1480語意 在此頁的第三段之倒數第三行:

原本是:
(於 Linux 2.6.10 與更早的版本,管線的容量與 PIPE_BUF 相同,這表示若管線只有包含一個單獨的位元組資料時會被視為不可寫的)。

修改的地方:
(於 Linux 2.6.10 與更早的版本,管線的容量與 PIPE_BUF 相同,這表示若管線只有包含一個位元組資料空間時,則會將管線會被視為不可寫)。

修改後的句子:
(於 Linux 2.6.10 與更早的版本,管線的容量與 PIPE_BUF 相同,這表示若管線只有一個位元組的空間時,則會將管線視為不可寫入)。

 2016/11/20 初版  Aaron Liao
 p1481語意在此頁表63-6 上方的註解段落:

原本是:
Linux 其中一個端點執行 close() 後,poll() 對於 UNIX domain socket 的行為與表 63-6 不同。如同其他旗標,poll() 會於 revents 額外傳回 POLLUP。

修改的地方:
Linux 系統上,在其中一個 UNIX domain socket 的端點執行 close() 後,poll() 的行為對於 UNIX domain socket 的行為與表 63-6 所示不同。除了如同其他旗標,poll() 會於 revents 額外傳回 POLLUP。

修改後的句子:
在 Linux 系統上,在其中一個 UNIX domain socket 的端點執行 close() 之後,poll() 的行為與表 63-6 所示不同。除了其他旗標,poll() 還會於 revents 額外傳回 POLLUP。

 2016/11/23 初版  Aaron Liao 
 p1481微調此頁的倒數第二行後方開始:

原本是:
poll()系統呼叫的實作替每一個檔案描述符呼叫核心 poll 常式,並將結果資訊置於對應的 revents 欄位中。

修改為:
poll()系統呼叫的實作替每一個檔案描述符呼叫核心 poll 常式,並將結果資訊置於對應的 revents 欄位中。
 
 2016/11/23 初版  Aaron Liao 
 p1482微調此頁的第一行:

原本是:
為了實作 select(),有一組巨集可用於將核心 poll 常式傳回的資訊轉換為對應 select() 傳回的事件類型:

修改為:
為了實作 select(),有一組巨集可用於將核心 poll 常式傳回的資訊轉換為對應 select() 傳回的事件類型: 

 2016/11/23 初版  Aaron Liao 
 p1482微調 在此頁的標題【API 差異性】 下方的第二點:

原本是:
由於 select() 的 fd_set 參數是屬於 value-result,若將 select() 呼叫置於迴圈中重複呼叫,我們必須每次對 fd_set 重新初始化。poll() 由於使用分開的 events(輸入)與 revents(輸出欄位),所以不需要這個動作。

修改的地方:
由於 select() 的 fd_set 參數是屬於用於傳參數與回傳結果value-result所以若將 select() 呼叫置於迴圈中重複呼叫,我們必須每次對 fd_set 重新初始化。poll() 由於使用分開的 events(輸入)與 revents(輸出欄位),所以不需要這個動作。

修改後的句子:
由於 select() 的 fd_set 參數是用於傳參數與回傳結果(value-result),所以若將 select() 呼叫置於迴圈中重複呼叫,則我們必須每次對 fd_set 重新初始化。poll() 由於使用分開的 events(輸入)與 revents(輸出欄位),所以不需要這個動作。

  2016/11/23 初版  Aaron Liao 
 p1482語意 在此頁的標題【API 差異性】 下方的第三點:

原本是:
select() 提供的 timeout 精度(微秒)比 poll() 提供的精度(毫秒)要高。(這兩個系統呼叫的超時精度雖受限於軟體時脈的粒度)。

修改的地方:
select() 提供的 timeout 精度(微秒)比 poll() 提供的精度(毫秒)要高(這兩個系統呼叫的超時精仍然受限於軟體時脈的粒度)。

修改後的句子:
select() 提供的 timeout 精密度(微秒)比 poll() 提供的精密度(毫秒)要高(這兩個系統呼叫的超時精準度仍然受限於軟體時脈的粒度)。

 2017/03/02 初版 Aaron Liao
 p1482微調 在此頁的標題【API 差異性】 下方第四點之第三行中間開始: 

原本是:
當進行描述符的 I/O 系統呼叫時,讓我們自行檢查錯誤以定義哪一個檔案描述符已經關閉。

修改為:
進行描述符進行 I/O 系統呼叫時,讓我們自行檢查錯誤以定義哪一個檔案描述符已經關閉。

 2016/11/23 初版 Aaron Liao
 p1483微調 在此頁標題【63.2.5 select() 與 poll() 的問題】 下方之第二點:

原本是:
在每次呼叫 select() 或 poll() 時,核心必須檢查所有指定的檔案描述符,以得知他們是否就緒。當所監控的大量檔案描述符是於密集裝載時,監控所需的時間會比下兩次操作所需的時間要多上許多。

修改的地方:
在每次呼叫 select() 或 poll() 時,核心必須檢查所有指定的檔案描述符,以得知他們是否就緒。當所監控的大量檔案描述符是既連續又密集於密集裝載時,這次操作監控所需的時間會比之後的兩個下兩次操作所需的時間要多上許多。

修改後的句子:
在每次呼叫 select() 或 poll() 時,核心必須檢查所有指定的檔案描述符,以得知他們是否就緒。當所監控的大量檔案描述符是既連續又密集時,這次操作所需的時間會比之後的兩個操作要多上許多。

 2016/11/23 初版 Aaron Liao
 p1484微調在此頁的第四行:

原本是:
在呼叫 select() 或 poll() 之後,程式必須檢測每個傳回的資料結構元素,以得知那些檔案描述符為就緒。

修改的地方: 
在呼叫 select() 或 poll() 之後,程式必須檢測每個傳回的資料結構成員元素,以得知些檔案描述符為就緒。

修改後的句子:
在呼叫 select() 或 poll() 之後,程式必須檢測每個傳回的資料結構成員,以得知哪些檔案描述符為就緒。


在此頁的第三段:

原本是:
select() 與 poll() 低落的效能評量(scaling)是源於 API 本身的限制,通常一個程式會重複地呼叫它們來以監控相同的檔案描述符集。然而,核心不會記住上次成功取得狀態的檔案描述符監控清單。

修改的地方:
select() 與 poll() 低落的效能評量(scaling)是源於 API 本身的限制,通常一個程式會重複地呼叫它們來監控相同的檔案描述符集。然而,核心不會記住上次成功取得狀態的檔案描述符監控清單。


 2016/11/23 初版 Aaron Liao
 p1485微調 在標題【範例程式】上方最後一段的註解 :

原本是:
在幾個 UNIX 平台裡(尤其是比較舊的)並沒有定義 O_ASYNC 常數供 fcntl() 使用。反而是名為 FASYNC 的常數,讓 glibc 將這個比較晚出現的名詞定義為 O_ASYNC 的代名詞。

修改的地方:
在幾個 UNIX 平台裡(尤其是比較舊的)並沒有定義 O_ASYNC 常數供 fcntl() 使用。反而有定義名為 FASYNC 的常數,因而 glibc 將這個比較晚出現的名詞定義為 O_ASYNC 的同義詞代名詞

修改後的句子:
在幾個 UNIX 平台裡(尤其是比較舊的)並沒有定義 O_ASYNC 常數供 fcntl() 使用。反而有定義名為 FASYNC 的常數,因而 glibc 將這個比較晚出現的名詞定義為 O_ASYNC 的同義詞。


在標題【範例程式】下方:

原本是:
列表 63-3 提供一個簡單的範例,教導如何使用訊號驅動 I/O。這個程式於標準輸入進行上述用於啟用訊號驅動 I/O 的步驟,並接著將終端機設置為 cbreak 模式(參考 62.6.3 節),讓輸入可以一次提供可讀一個字元。

修改的地方:
列表 63-3 提供一個簡單的範例,教導如何使用訊號驅動 I/O。這個程式執行上述對標準輸入進行上述用於啟用訊號驅動 I/O 的步驟,並接著將終端機設置為 cbreak 模式(參考 62.6.3 節),使得可以一次從輸入讀取一個字元讓輸入可以一次提供可讀一個字元

修改後的句子:
列表 63-3 提供一個簡單的範例,教導如何使用訊號驅動 I/O。這個程式執行上述對標準輸入啟用訊號驅動 I/O 的步驟,並接著將終端機設置為 cbreak 模式(參考 62.6.3 節),使得可以一次從輸入讀取一個字元。

 2016/11/23 初版 Aaron Liao
 p1491語意在此頁的倒數第七行:

原本是:
若我們執行一個 F_SETSIG操作以設置 sig 為 0,那麼我們會回到預設的行為:傳遞 SIGIO,以及處理常式不會支援 siginfo_t 參數。

修改的地方:
若我們執行一個 F_SETSIG操作時將以設置 sig 設定為 0,那麼我們會回歸回到預設的行為:傳遞 SIGIO,以及不提供 siginfo_t 參數給處理常式不會支援 siginfo_t 參數

修改後的句子:
若我們在執行一個 F_SETSIG操作時將 sig 設定為 0,那麼我們會回歸預設的行為:傳遞 SIGIO,以及不提供 siginfo_t 參數給處理常式。

 2016/11/23 初版 Aaron Liao
 p1492微調在表 63-7 下方的段落:

原本是:
在一個單純以輸入驅動的應用程式中,我們能更進一步地改善F_SETSIG的使用。我們可以鎖住被點名的「可I/O」訊號,然後再透過呼叫sigwaitinfo()或sigtimedwait()(22.10節)接受排隊中的訊號,

而非以訊號處理常式監控I/O事件。這些系統呼叫傳回的siginfo_t結構內容與傳遞給以SA_SIGINFO建立的訊號處理常式有相同的資料。以這個方法接受的訊號傳給我們一個事件處理同步模型,好處是我們可以比select()或poll()更有效率地注意檔案描述符的發生事件。

修改的地方:(排版問題,兩個段落要合併為一個段落)
在一個單純以輸入驅動的應用程式中,我們能更進一步地改善F_SETSIG的使用。我們可以阻塞(block)鎖住被點名的「可I/O」訊號,然後再透過呼叫sigwaitinfo()或sigtimedwait()(22.10節)接受排隊中的訊號,而非以訊號處理常式監控I/O事件。這些系統呼叫傳回的siginfo_t結構內容與傳遞給以SA_SIGINFO建立的訊號處理常式有相同的資料。以這個方法接受訊號傳給我們一個事件處理同步模型,好處是我們可以比select()或poll()更有效率地注意檔案描述符發生事件。

修改後的句子:
在一個單純以輸入驅動的應用程式中,我們能更進一步地改善F_SETSIG的使用。我們可以阻塞(block)被點名的「可I/O」訊號,然後再透過呼叫sigwaitinfo()或sigtimedwait()(22.10節)接受排隊中的訊號,而非以訊號處理常式監控I/O事件。這些系統呼叫傳回的siginfo_t結構內容與傳遞給以SA_SIGINFO建立的訊號處理常式有相同的資料。以這個方法接受訊號回傳給我們一個事件處理同步模型,好處是我們可以比select()或poll()更有效率地注意在檔案描述符所發生的事件。
 
 2016/11/23 初版 Aaron Liao
 p1493訂正此頁的標題【63.4 epoll API】 上方的註解:

原本是:
由於 F_SETOWN_EX 與 F_GETOWN_EX 操作將形成群組 ID 表示為正數,當使用小於 4096 的行程群組 ID 時,F_GETOWN_EX 不用面臨之前所描述的問題

將結尾修改為句號:
由於 F_SETOWN_EX 與 F_GETOWN_EX 操作將形成群組 ID 表示為正數,當使用小於 4096 的行程群組 ID 時,F_GETOWN_EX 不用面臨之前所描述的問題

 2016/11/25 初版  Aaron Liao
 p1494微調 在標題【63.4.1 建立 epoll 實體:epoll_create()】 上方段落之倒數第二項:

原本是:
epoll_ctl()系統呼叫操控與 epoll 實體有關的興趣清單。使用 epoll_ctl(),我們能夠增加新的檔案描述符到清單中、從清單移除一個已存在的描述符、及修改定義所監控的描述符之事件的遮罩。

修改的地方:
epoll_ctl()系統呼叫操控與 epoll 實體有關的興趣清單。我們可以使用 epoll_ctl(),我們能夠將一個新的檔案描述符新增到清單中、從清單移除一個已存在既有的描述符、及修改決定定義所監控描述符之事件遮罩。

修改後的句子:
epoll_ctl()系統呼叫操控與 epoll 實體有關的興趣清單。我們可以使用 epoll_ctl()將一個新的檔案描述符新增到清單中、從清單移除一個既有的描述符、及修改決定所監控描述符之事件遮罩。



在標題【63.4.1 建立 epoll 實體:epoll_create()】 上方段落之最後一項:

原本是:
epoll_wait 系統呼叫從與 epoll 實體有關的就緒清單中傳回項目。

修改為:
epoll_wait() 系統呼叫從與 epoll 實體有關的就緒清單中傳回項目。

 2016/11/25 初版  Aaron Liao 
 p1495語意 在標題【63.4.2 修改 epoll 興趣清單:epoll_ctl()】 上方的註解段落:

原本是:
從核心 2.6.27 開始,Linux 支援新的 epoll_create1() 系統呼叫。這個系統呼叫執行與 epoll_create() 相同的任務,但是捨棄過期的 size 參數,並增加可以用於監控系統呼叫行為的 flags 參數。目前有一個已支援的旗標:EPOLL_CLOEXEC,使核心啟用 close-on-exec 旗標(FD_CLOEXEC)做為新的檔案描述符。這個旗標很有用,理由與 4.3.1 節描述的 open() O_CLOEXEC 旗標一樣。

修改的地方:
從核心 2.6.27 開始,Linux 支援新的 epoll_create1() 系統呼叫。這個系統呼叫執行的任務與 epoll_create() 相同的任務,但是捨棄了過時過期的 size 參數,並增加可以用於監控系統呼叫行為的 flags 參數。目前已提供一個支援的旗標:EPOLL_CLOEXEC,使核心對新的檔案描述符啟用 close-on-exec 旗標(FD_CLOEXEC)做為新的檔案描述符。這個旗標很有用,理由 4.3.1 節描述的 open() O_CLOEXEC 旗標一樣

修改後的段落:
從核心 2.6.27 開始,Linux 支援新的 epoll_create1() 系統呼叫。這個系統呼叫執行的任務與 epoll_create() 相同,但是捨棄了過時的 size 參數,並增加可以用於監控系統呼叫行為的 flags 參數。目前已提供一個旗標:EPOLL_CLOEXEC,使核心對新的檔案描述符啟用 close-on-exec 旗標(FD_CLOEXEC)。這個旗標很有用處,理由同 4.3.1 節描述的 open() O_CLOEXEC 旗標。

 2016/11/25 初版  Aaron Liao 
 p1495微調 找到標題【63.4.2 修改 epoll 興趣清單:epoll_ctl()】下方,在 epoll_ctl() 函式原型下方段落的第四行中間:

原本是:
然而,fd 不能為普通檔案或目錄的檔案描述符(錯誤結果 EPERM)。

修改的地方:
然而,fd 不為普通檔案或目錄的檔案描述符(結果會產生錯誤結果 EPERM錯誤)。

修改後的句子:
然而,fd 不可為普通檔案或目錄的檔案描述符(結果會產生 EPERM錯誤)。

 2016/11/25 初版  Aaron Liao 
 p1498微調 在標題【epoll 事件】下方的段落:

原本是:
當我們呼叫epoll_ctl()時,能設定於ev.events的位元值(bit value);以及由epoll_wait()於evlist[].events欄位傳回的位元值都於表63-8中呈現。大部分這些位元的名稱與poll()相對應的事件位元相同,並額外以E開頭。(除了EPOLLET與EPOLLONESHOT例外,後面將有更多的說明)。這樣對應的原因是因為,當指定做為epoll_ctl()輸入或做為epoll_wait()的傳回輸出時,這些位元可以精確地傳達並與epoll()相對應的事件位元具有相同的意義。

修改的地方:
表63-8所示的位元值可用於:當我們呼叫epoll_ctl()時,能設定於ev.events指定的位元值(bit value);以及epoll_wait()於evlist[].events欄位傳回的位元值都於表63-8中呈現大部分這些位元的名稱會額外以E開頭,而且大多數相對應的poll()相對應事件位元相同,並額外以E開頭。(除了EPOLLET與EPOLLONESHOT例外,後面將詳述有更多的說明)。這樣對應的原因是因為,當指定做為epoll_ctl()的指定輸入或做為epoll_wait()的傳回輸出時,這些位元可以精確地傳達epoll()相對應的poll()事件位元具有相同意義。

修改後的段落:
表63-8所示的位元值可用於:呼叫epoll_ctl()時於ev.events指定的位元值(bit value);以及epoll_wait()於evlist[].events欄位傳回的位元值。這些位元的名稱會額外以E開頭,而且大多數與相對應的poll()事件位元相同(除了EPOLLET與EPOLLONESHOT例外,後面將詳述)。這樣對應的原因是,當做為epoll_ctl()的指定輸入或epoll_wait()的傳回輸出時,這些位元可以精確地傳達且與相對應的poll()事件位元具有相同意義。


此頁最後的註解段落:

原本是:
Linux 3.5新增新的epoll旗標-「EPOLLWAKEUP」,這個新旗標可以讓呼叫epoll_ctl()時避免系統暫停(suspend),即使指定的檔案描述符已經有epoll事件發生。這個旗標的使用需要呼叫者具備EPOLLWAKEUP能力(已於Linux 3.5新增的功能)。

修改的地方:
Linux 3.5新增新的epoll旗標-「EPOLLWAKEUP」,這個新旗標可以避免在呼叫epoll_ctl()時因為指定的檔案描述符發生了epoll事件而導致避免系統暫停(suspend)即使指定的檔案描述符已經有epoll事件發生。這個旗標的使用需要呼叫者需要具備EPOLLWAKEUP能力(已於Linux 3.5新增的功能)才能使用此旗標

修改後的句子:
Linux 3.5新增了新的epoll旗標-「EPOLLWAKEUP」,這個新旗標可以避免在呼叫epoll_ctl()時因為指定的檔案描述符發生了epoll事件而導致系統暫停(suspend),呼叫者需要具備EPOLLWAKEUP能力(已於Linux 3.5新增的功能),才能使用此旗標。
 
 2016/11/26 初版  Aaron Liao 
 p1499語意 在標題【範例程式】上方的段落之倒數第三行:

原本是:
如果想要,我們可以不斷地使用epoll_ctl()重啟這個檔案描述符的監控。(對於這個目的,我們不能使用EPOLL_CTL_ADD操作,因為失效的檔案描述符仍然是epoll興趣清單的一份子)。

修改的地方:
若有需要如果想要,我們可以不斷地使用epoll_ctl()的EPOLL_CTL_MOD操作重啟這個檔案描述符的監控對於這個目的,我們不能為此而使用EPOLL_CTL_ADD操作,因為失效的檔案描述符仍然是epoll興趣清單的一份子)。

修改後的句子:
若有需要,我們可以不斷地使用epoll_ctl()的EPOLL_CTL_MOD操作重啟這個檔案描述符的監控(我們不能為此而使用EPOLL_CTL_ADD操作,因為失效的檔案描述符仍然是epoll興趣清單的一份子)。

 2016/11/26 初版  Aaron Liao
 p1499微調 在標題【範例程式】下方的第三點之第一小點:

原本是:
在epoll_wait()呼叫之後,程式檢查一個EINTR傳回值⑥,這可能發生於程式在epoll_wait()呼叫過程中被訊號停止,並由SIGCONT復原。(參考21.5節)若這種情況發生,程式會重新啟動epoll_wait()呼叫。

修改的地方:
在epoll_wait()呼叫之後,程式檢查一個EINTR傳回值⑥,這可能發生於(若程式在epoll_wait()呼叫過程中受到訊號停止,然後由SIGCONT訊號復原,則可能會發生。(,請參考21.5節)若這種情況發生,程式會重新啟動epoll_wait()呼叫。

修改後的句子:
在epoll_wait()呼叫之後,程式會檢查一個EINTR傳回值⑥(若程式在epoll_wait()呼叫過程中受到訊號停止,然後由SIGCONT訊號復原,則可能發生,請參考21.5節)。若這種情況發生,則程式會重新啟動epoll_wait()呼叫。

 2016/11/27 初版  Aaron Liao 
 p1500微調在此頁的第一行:

原本是:
下列的shell作業階段紀錄展示了列表63-5程式之使用。我們使用兩個終端機視窗,在其中一個視窗,我們使用列表63-5中的程式監控兩個FIFO的輸入(這個程式開啟用於讀取的每個FIFO,只有在另一個行程開啟FIFO用於寫入時完成,如同44.7節所述)。

修改的地方:
下列的shell作業階段紀錄示範如何使用展示了列表63-5程式之使用。我們使用兩個終端機視窗,在其中一個視窗執行,我們使用列表63-5的程式監控兩個FIFO的輸入(這個程式開啟用於讀取的每個FIFO,只有在另一個行程開啟FIFO用於寫入時完成在另一個行程完成開啟FIFO做為寫入之後,此程式開啟做為讀取的FIFO才會完成開啟,如同44.7節所述)。

修改後的句子:
下列的shell作業階段紀錄示範如何使用列表63-5的程式。我們使用兩個終端機視窗,在其中一個視窗執行列表63-5的程式來監控兩個FIFO的輸入(在另一個行程完成開啟FIFO做為寫入之後,此程式開啟做為讀取的FIFO才會完成開啟,如同44.7節所述)。

 2016/11/27 初版  Aaron Liao 
 p1500語意 找到此頁最下面的程式碼,在它們上面的說明:

原本是:
現在我們透過將監控程式帶到前景(foreground)以回復執行,在epoll_wait()傳回兩個事件點的時候:

修改的地方:
現在我們透過將監控程式帶到前景(foreground)以回復執行,此時,epoll_wait()傳回兩個事件點的時候

修改後的句子:
現在我們透過將監控程式帶到前景(foreground)以回復執行,此時,epoll_wait()會傳回兩個事件:

 2016/11/27 初版  Aaron Liao 
 p1503微調此頁標題【63.4.4 你可以靠近一點看 epoll 的語意】,第二段的第一點:

原本是:
若我們用dup()(或類似的方式)複製一個epoll檔案描述符,那麼描述符副本會跟原本的描述符一樣,都是參照到相同的epoll的興趣清單與就緒清單。我們能透過epoll_ctl()呼叫的epfd參數指定檔案描述符或修改興趣清單。同樣地,我們能以指定檔案描述符做為epoll_wait()呼叫的epfd參數,並從就緒清單解析項目。

修改的地方:
若我們用dup()(或類似的方式)複製一個epoll檔案描述符,那麼描述符副本會跟原本的描述符一樣,都是參照到相同的epoll的興趣清單與就緒清單。我們能透過epoll_ctl()呼叫的epfd參數指定檔案描述符或修改興趣清單。同樣地,我們可以將能以指定檔案描述符指定做為epoll_wait()呼叫的epfd參數,從就緒清單中取得解析項目。

修改後的句子:
若我們用dup()(或類似的方式)複製一個epoll檔案描述符,那麼描述符副本會跟原本的描述符一樣,都是參照到相同的epoll的興趣清單與就緒清單。我們能透過epoll_ctl()呼叫的epfd參數指定檔案描述符或修改興趣清單。同樣地,我們可以將檔案描述符指定做為epoll_wait()呼叫的epfd參數,以從就緒清單中取得項目。

 2016/11/27 初版  Aaron Liao 
 p1503微調 在倒數第三行開始: 

原本是:
這些語意可以導致第一次見到時會令人驚訝的一些行為。假設我們執行如列表63-6所示的程式碼,在這個程式碼中的epoll_wait()呼叫會告訴我們fd1檔案描述符已經是就緒(換句話說,evlist[0].data.fd會等於fd1),即使fd1已經關閉了。這是因為仍然有一個開啟檔案描述符(fd2),參考的開啟檔案描述符在epoll興趣清單內。類似的情境發生於兩個行程都持有同一個開啟檔案描述符的複本(通常是fork()造成的結果),而執行epoll_wait()的行程已經關閉了它的檔案描述符,可是另一個行程仍然將描述符複本保持在開啟狀態。

修改的地方:
這些語意可以導致令人初次第一次見到時會訝異會令人驚訝的一些行為。假設我們執行列表63-6所示的程式碼,即使fd1已經關閉了,在這個程式碼中的epoll_wait()呼叫會告訴我們fd1檔案描述符已經是就緒(換句話說,evlist[0].data.fd會等於fd1),即使fd1已經關閉了。這是因為仍然有一個開啟檔案描述符(fd2),參考的開啟檔案描述符在epoll興趣清單內。類似的情境發生於兩個行程都持有同一個開啟檔案描述符的複本(通常是fork()造成的結果),而執行epoll_wait()的行程已經關閉了它的檔案描述符,可是另一個行程仍然將描述符複本保持在開啟狀態。

修改後的段落:
這些語意導致令人初次見到時會訝異的一些行為。假設我們執行列表63-6的程式碼,即使fd1已經關閉了,在這個程式碼中的epoll_wait()呼叫仍會告訴我們fd1檔案描述符已經是就緒的(換句話說,evlist[0].data.fd會等於fd1)。這是因為仍然有一個開啟檔案描述符(fd2),其參考的開啟檔案描述符仍在epoll興趣清單內。類似的情境發生於兩個行程都持有同一個開啟檔案描述符的複本(通常是fork()造成的結果),而執行epoll_wait()的行程已經關閉了它的檔案描述符,可是另一個行程仍然將描述符複本保持在開啟狀態。

 2016/11/27 初版  Aaron Liao 
 p1504微調在標題【63.4.5 epoll與I/O多工的效能比較】下方:

原本是:
表63-9呈現我們使用poll()、select()與epoll()監控0到N-1範圍的N個相近的檔案描述符結果(於Linux 2.6.25)。(安排這個測試在每個監控操作期間,剛好一個隨機選擇的檔案描述符為就緒)由此表,我們可以看到所監控的檔案描述符數量越多時,poll()與select()的表現會越差。相對地,當N不斷增加時,epoll的效能幾乎不會下降。(當N增加時,效能的微幅下降有可能是因為達到了測試系統的CPU快取限制)。

修改的地方:
表63-9呈現我們使用poll()、select()與epoll()監控0到N-1範圍的N個相近的檔案描述符結果(於Linux 2.6.25)。(安排這個測試在每個監控操作期間,使得剛好一個隨機選擇的檔案描述符為就緒)我們由此表,我們可以看到:當所監控的檔案描述符數量越多時,poll()與select()的表現會越差。相對地,當N不斷增加時,epoll的效能幾乎不會下降。(當N增加時,效能的微幅下降有可能是因為達到了測試系統的CPU快取限制)。

修改後的段落:
表63-9呈現我們使用poll()、select()與epoll()監控0到N-1範圍的N個相近的檔案描述符結果(於Linux 2.6.25)。(安排這個測試在每個監控操作期間,使得剛好有一個隨機選擇的檔案描述符為就緒)我們由此表可以看到:當所監控的檔案描述符數量越多時,poll()與select()的表現會越差。相對地,當N不斷增加時,epoll的效能幾乎不會下降。(當N增加時,效能的微幅下降有可能是因為達到了測試系統的CPU快取限制)。

 2016/11/27 初版  Aaron Liao
 p1504訂正在此頁最下方的註解段落:

原本是:
為了這個測試目的,將glibc標頭檔檔中的FD_SETSIZE更改為16,384,以允許測試程式可以用select()監控大量的檔案描述符。

修改為:
為了這個測試目的,將glibc標頭檔檔中的FD_SETSIZE更改為16,384,以允許測試程式可以用select()監控大量的檔案描述符。

 2016/11/27 初版  Aaron Liao 
 p1506微調 在此頁的第九行:

原本是:
若要採用邊緣觸發通知,我們於ev.events指定EPOLLET旗標,當呼叫epoll_ctl()時:

修改為:
若要採用邊緣觸發通知,則在執行epoll_ctl()呼叫時,要在ev.events指定EPOLLET旗標:
 
 2016/11/27 初版  Aaron laio 
 p1513微調在 63.6 小結下方的第三段之第三行後面:

原本是:
當監控大量的檔案描述符,這個機制明顯提供比I/O多工更優異的性能。

修改為:
當監控大量的檔案描述符,這個機制明顯提供比I/O多工更優異的性能。

 2016/11/27 初版  Aaron laio
 p1514微調 在此頁第一段的第四行後面:

原本是:
而epoll可以任何一個模型下運作(預設為準位觸發)。 

修改為:
而epoll可以任何一個模型下運作(預設為準位觸發)。 


習題 63-2

原本是:
設計一個echo伺服器(參考60.2與60.3節),來處理TCP與UDP客戶端。為了達成這件事,伺服器必須建立一個監聽式TCP socket與一個UDP socket,然後使用任何在本章介紹的技術來監控這兩個socket。

修改為:
設計一個echo伺服器(參考60.2與60.3節),來處理TCP與UDP客戶端。為了達成這件事,伺服器必須建立一個監聽式TCP socket與一個監聽式UDP socket,然後使用任何在本章介紹的技術來監控這兩個socket。

 2016/11/27 初版 Aaron laio
 p1555語意此頁的第二段第二行中間開始:

原本是:
這在其他的UNIX平台將不會發生,第一個非選項(644)的發生會確保 getopt() 在剩下的命令列中尋找選項

修改的地方:
不過這在其他的UNIX平台將不會發生,因為第一個出現的非選項(644)的發生會確保 getopt() 停止繼續在剩下的命令列中尋找選項

修改後的句子:
不過這在其他的UNIX平台將不會發生,因為第一個出現的非選項(644)可確保 getopt() 停止繼續在剩下的命令列中尋找選項。

 2016/11/18 初版  Aaron Liao 
 p1558語意在此頁的倒數第四行後面:

原本是:
execl() 很可能會在整數 0 的附近接收到一些隨機位元,從導致將結果值解釋為一個隨機指標(不為null)。

修改的地方:
execl() 很可能會收到整數 0 相鄰
位元數值附近接收到一些隨機位元因而導致指標內容可能是任意的隨機值將結果值解釋為一個隨機指標(不為null)。

修改後的句子:
execl() 很可能會收到與整數 0 相鄰
位元的數值,因而導致指標內容可能是任意的隨機值(不為null)。
 
 2016/11/28 初版  Aaron Liao 
 p1559語意在此頁的最後一段(即註解段落),此段落的第二行:

原本是:
char *型別指標和 void *型別指標要求要有相同的內部表示。

修改為:
要求對 char *型別指標和 void *型別指標要求要有相同的內部表示。

 2016/11/18 初版  Aaron Liao 
 p1574訂正在第15章的15-5習題,此題目的倒數第二行:

原本是:
然而請注意,這個解法並非執行緒安全的(thread-saft),因為執行緒會共用行程的umask設定。

修改為:
然而請注意,這個解法並非執行緒安全的(thread-safe),因為執行緒會共用行程的umask設定。

 2016/10/27 初版 Aaron Liao
 p1575微調在第22章的22-2習題:

原本是:
如同大多數的UNIX實作,Linux在即時訊號(realtime signal)之前會傳輸標準訊號(SUSv3並未要求)。

修改為:
如同大多數的UNIX實作,Linux在傳遞即時訊號(realtime signal)之前會傳輸標準訊號(SUSv3並未要求)。

 2016/10/27 初版 Aaron Liao
 p1577微調在第27章的27-6習題:

原本是:
傳輸SIGCHLD訊號給父行程。若SIGCHLD處理常式試圖呼叫wait(),則呼叫將傳回錯誤(錯誤號為ECHILD),表示沒有可傳回狀態的子行程。

修改為:
傳輸SIGCHLD訊號給父行程。若SIGCHLD處理常式試圖呼叫wait(),則呼叫將傳回錯誤(錯誤號為ECHILD),表示沒有可傳回狀態的子行程。

 2016/10/27 初版 Aaron Liao
 p1578微調在第33章的33-2習題: 

原本是:
在子行程終止時產生的SIGCHLD 訊號是process-directed,...

修改為:
在子行程終止時產生的SIGCHLD 訊號是行程導向的(process-directed,...


在第34章的34-5習題,第二行: 

原本是:
若在再次產生SIGTSTP訊號之前,這個訊號被解除了阻塞,則會有一小段的時間窗口

將紅色字取代為藍色字:
若在再次產生SIGTSTP訊號之前,這個訊號被解除了阻塞,則會有一小段時間的空窗期

 2016/10/27 初版 Aaron Liao
 p1582語意在第57章的57-4習題:

原本是:
在Linux上,sendto()呼叫會失敗並傳回EPERM錯誤。在其它一些UNIX系統上會產生一個不同的錯誤。一些UNIX實作並不要求這一限制,而是會讓一個已連接的UNIX domain資料包(datagram)socket從其發送者處接收一個資料包,而不是從其對等處接收一個資料包。

修改的地方:
在Linux上,sendto()呼叫會失敗並傳回EPERM錯誤。在其它一些UNIX系統上會產生一個不同的錯誤結果一些UNIX實作並不要求這一則沒有此限制,而是會讓一個已連接的UNIX domain datagram socket 接收不是來自其彼端(peer)的資料包(datagram)。資料包socket 從其發送者處接收一個資料包(datagram),而不是從其對等處接收一個資料包。

修改後的句子:
在Linux上,sendto()呼叫會失敗並傳回EPERM錯誤。在其它一些UNIX系統上會產生一個不同的結果。有一些UNIX實作則沒有此限制,而是會讓一個已連接的UNIX domain datagram socket 接收不是來自其彼端(peer)的資料包(datagram)。

 2016/10/27 初版 Aaron Liao




Comments