unix環境高階程式設計---標準i/o庫
在前面《unix環境高階程式設計----檔案描述符**》一文中所講的i/o函式都是針對檔案描述符。而對於標準i/o庫,它們的操作都是圍繞流來進行的。當用標準i/o庫開啟或建立乙個檔案時,我們已經使乙個流與檔案相結合。
一、流和file物件
當開啟乙個流時,標準i/o函式fopen返回乙個指向file物件的指標。該物件通常是乙個結構,它包含了i/o庫為管理該流所需要的所有資訊:用於實際i / o的檔案描述符,指向流快取的指標,快取的長度,當前在快取中的字元數,出錯標誌等等。
應用程式沒有必要檢驗file物件。為了引用乙個流,需將file指標作為引數傳遞給每個標準i/o函式。在《unix環境高階程式設計》一書中,我們稱指向file物件的指標(型別為file*)為檔案指標。
二、標準i/o庫的快取
標準i/o提供快取的目的是盡可能少的使用read和write呼叫量,從而加速對檔案的讀和寫操作。但是不幸的是標準i/o庫最讓人迷惑的恰好也是它的快取。為了詳細說明快取的機制,必須先了解下為什麼有了這個快取就能提供檔案的操作效率。
使用者程式呼叫標準i/o庫函式讀寫檔案,而這些庫函式要通過系統呼叫把讀寫請求傳給核心,最終由核心驅動磁碟或裝置完成i/o操作。標準i/o庫為每個開啟的檔案分配乙個i/o緩衝區以加速讀寫操作,通過檔案的file結構體可以找到這個緩衝區,使用者呼叫讀寫函式大多數時候都在i/o緩衝區中讀寫,只有少數時候需要把讀寫請求傳給核心。以fgetc/fputc為例,當使用者程式第一次呼叫fgetc讀乙個位元組時,fgetc函式可能通過系統呼叫進入核心讀1k位元組到i/o緩衝區中,然後返回i/o緩衝區中的第乙個位元組給使用者,把讀寫位置指向i/o緩衝區中的第二個字元,以後使用者再調fgetc,就直接從i/o緩衝區中讀取,而不需要進核心了,當使用者把這1k位元組都讀完之後,再次呼叫fgetc時,fgetc函式會再次進入核心讀1k位元組到i/o緩衝區中。標準i/o庫之所以會從核心預讀一些資料放在i/o緩衝區中,是希望使用者程式隨後要用到這些資料,標準i/o庫的i/o緩衝區也在使用者空間,直接從使用者空間讀取資料比進核心讀資料要快得多。另一方面,使用者程式呼叫fputc通常只是寫到i/o緩衝區中,這樣fputc函式可以很快地返回,如果i/o緩衝區寫滿了,fputc就通過系統呼叫把i/o緩衝區中的資料傳給核心,核心最終把資料寫回磁碟。有時候使用者程式希望把i/o緩衝區中的資料立刻傳給核心,讓核心寫回裝置,這稱為flush操作,對應的庫函式是fflush,fclose函式在關閉檔案之前也會做flush操作。
下圖一以fgets/fputs示意了i/o緩衝區的作用,使用fgets/fputs函式時在使用者程式中也需要分配緩衝區(圖中的buf1和buf2),注意區分使用者程式的緩衝區和c標準庫的i/o緩衝區。
圖一 i/o快取區
標準i/o庫提供了三種型別的快取:
1) 全快取:如果緩衝區寫滿了就寫回核心。常規檔案通常是全緩衝的。
2) 行快取:如果使用者程式寫的資料中有換行符就把這一行寫回核心,或者如果緩衝區寫滿了就寫回核心。標準輸入和標準輸出對應終端裝置時通常是行緩衝的。
行快取有兩個限制:
第乙個是行快取區的快取長度是固定,系統一般預設為1k,所以只要行快取區滿了,即使沒有寫乙個新換行符,系統也會執行i/o操作;關於這一點,可以從下面的例子看出來。
第二個是任何時候只要通過標準輸入輸出庫要求從( a )乙個不帶快取的流,或者( b )乙個行快取的流(它預先要求從核心得到資料)得到輸入資料,那麼就會造成重新整理所有行快取輸出流。
example 01.c
#include
int main()
printf("hello world");
whlie(1);
return 0;
編譯執行時會發現終端什麼都沒有輸出。如果把whlie(1)去掉,就會在終端列印出hello world。
example 02.c
#include
int main()
printf("hello world\n");
whlie(1);
return 0;
編譯執行時會發現終端印出hello world。
example 03.c
#include
int main()
printf("hello world ...hello world");//...代表1024-11*2個位元組
whlie(1);
return 0;
編譯執行時會發現終端列印出hello world ...hello world。以上三個例子足以說明行快取型別的快取區長度是固定的。寫入快取區的資料為換行符或長度超過快取區長度時系統會執行i/o操作。
3) 不帶快取:使用者程式每次調庫函式做寫操作都要通過系統呼叫寫回核心。標準錯誤輸出通常是無緩衝的,這樣使用者程式產生的錯誤資訊可以盡快輸出到裝置。
void setbuf(file *fp, char *buf) ;
或int setvbuf(file *fp, char *buf, int mode, size_t size) ;
返回:若成功則為0,若出錯則為非0
下圖二是setbuf和setvbuf函式各選項說明,可以明顯看出函式setvbuf功能更強大一些。
圖二 setbuf和setvbuf函式各選項說明
unix環境高階程式設計 標準IO
標準io庫 不僅在unix上,在很多作業系統上都實現了標準的io庫,它處理了很多細節,例如緩衝區分配,優化長度執行io等。流和file物件 對於標準的io庫,它們的操作是圍繞流 stream 進行的。當用標準io庫開啟或建立乙個檔案時,已經使乙個流和乙個檔案相關聯,標準的io檔案流可用於單位元組和多...
Unix環境高階程式設計 三 標準I O庫
標準i o庫是iso c的標準,在很多作業系統上面都實現。unix檔案i o函式都是針對檔案描述符的,當開啟乙個檔案的時候,返回該檔案描述符用於後續的i o操作。而對於標準i o庫,操作則是圍繞流進行,當用標準i o庫開啟或者建立乙個檔案時,使得乙個流與檔案相關聯。標準i o庫使用了緩衝技術,使用緩...
UNIX 環境高階程式設計 標準IO 未完
函式原型 file fopen const char path,const char mode 函式功能 開啟乙個檔案 函式引數 path 字串包含欲開啟的檔案路徑及檔名 mode 字串則代表著流形態。包含下面的幾種模式 mode有下列幾種形態字串 r 以唯讀方式開啟檔案,該檔案必須存在。r 以可讀...