APUE之第5章——標準I/O庫

1、知識回顧:文件I/O
  • 文件 I/O 是不帶緩衝的 I/O(unbuffered I/O),指每一個 read 和 write 都調用內核中的一個系統調用。
  • 對於內核而言,全部打開的文件都經過文件描述符引用,即不帶緩衝的 I/O 經過文件描述符的方式來引用一個文件。
  • 大多數文件 I/O 只需用到5個函數:open、read、write、lseek、close。
2、標準I/O
  • 標準 I/O 庫由 ISO C 標準說明。
  • 標準 I/O 庫的操做圍繞流進行,即帶緩衝的 I/O 則經過文件流(stream)的方式來引用文件。
  • 引入標準 I/O 庫的目的是爲了提升 I/O 的效率,儘量地減小使用 read 和 write 調用的次數。由於系統調用會消耗較多的資源,標準 I/O 庫提供了緩衝,能夠經過累積必定量的數據後,集中寫入到實際的文件中來減小系統調用。這樣文件的讀寫就要通過緩衝區作緩衝,從而提升 I/O 效率。
    假設,每一個人家裏喝的水都是從自來水廠來的,自來水廠的水又是從水源地來的,這當中流動的水,就是水流,能夠理解爲IO流,
    在 UNIX 中,UNIX 就是自來水廠,水源地就是源,家就是目的。則從水源到自來水廠的水流,就是IO輸入流,從自來水廠到家的水流,就是IO輸出流。
    若是沒有蓄水池,則每次用水都要運送一次。一萬次用水就是運送一萬次,這樣的效率很低。若在水源地與自來水廠、自來水廠與家之間分別建造蓄水池,
    則自來水廠能夠隨時從蓄水池中取水、爲用戶供水,咱們須要用水時也能隨時有水可用。這裏的蓄水池就能夠類比成緩衝。
 
3、標準 I/O 與文件 I/O 的區別
 
  標準I/O
文件 I/O
遵循標準
標準 I/O 被稱爲高級磁盤I/O,遵循 ANSI C 相關標準。只要開發環境中有標準 I/O庫,標準 I/O 就可使用。
文件 I/O 被稱爲低級磁盤 I/O,遵循 POSIX 相關標準。任何兼容 POSIX 標準的操做系統上都支持文件 I/O。
緩衝機制
標準 I/O 默認採用緩衝機制,能夠當作是在文件 I/O 的基礎上封裝了緩衝機制。先讀寫緩衝區,必要時再訪問實際文件,從而減小了系統調用的次數。
低級 I/O 通常沒有采用緩衝,須要本身建立緩衝區。經過文件 I/O 讀寫文件時,每次操做都會執行相關係統調用。這樣處理的好處是直接讀寫實際文件,壞處是頻繁的系統調用會增長系統開銷。
操做設備
標準 I/O 中用 FILE(流)表示一個打開的文件,一般用來訪問普通文件。針對的是控制檯,打印輸出到屏幕等。
文件 I/O 中用文件描述符表現一個打開的文件,能夠訪問不一樣類型的文件如普通文件、設備文件和管道文件等。主要針對的是文件操做、讀寫硬盤等。
如下爲標準 I/O 函數和文件 I/O 函數的對比
打開
fopen,freopen,fdopen
open
fopen與open
標準 I/O 使用 fopen 函數打開一個指定文件。
pathname 是文件名。type 參數指定對I/O流的讀、寫方式,主要有"r"(只讀打開),"r+"(讀寫打開),"w"(只寫打開),"w+"(讀寫打開),"a"(追加打開)、"a+"(讀和追加打開),能夠加上字母 b 用以指定以二進制模式打開文件。
 
若成功,會返回一個 FILE 類型的指針,做爲咱們打開文件的憑據,後面全部對這個文件的操做都須要使用這個文件指針,使用以後要調用 fclose 函數釋放資源。
若失敗,會返回一個指向 NULL 的指針,表示文件打開失敗了,能夠經過 errno 獲取到具體失敗的緣由。
文件 I/O 使用 open 函數打開或建立一個文件。
path 參數是要打開或建立的文件名。aflag 參數可用來講明文件的打開模式,主要有 O_RDONLY(只讀打開),O_WRONLY(只寫打開),O_RDWR(讀、寫打開) 等。
 
若成功,返回文件描述符;失敗則返回-1。
關閉
fclose
close
fclose與close
標準 I/O 使用 fclose 函數關閉一個打開的流。
若是成功關閉,返回 0,失敗則返回 EOF。
文件 I/O 使用 close 函數關閉一個打開的文件。
若是成功關閉,返回 0,失敗則返回-1,而不是 EOF。
getc,fgetc,getchar,
fgets,gets,
fread
read
 
標準 I/O 能夠用 3 種方式進行文件讀取。
  • 每次一個字符的I/O
函數getchar等同於getc(stdin)。前兩個函數的區別是,getc可被實現爲宏,而fgetc不能實現宏。
若成功,返回下一個字符;若已達到文件尾端或出錯,則返回 EOF。
  • 每次一行的I/O
這兩個函數都指定了緩衝區的地址,讀入的行將送入其中。gets從標準輸入讀,而fgets從指定的流讀。
gets(不建議使用):接受一個參數,不判斷目標數組是否可以容納讀入的字符,可能致使存儲溢出;
fgets使用三個參數:第一個參數和gets同樣,用於存儲輸入的地址,第二個參數爲整數,表示輸入字符串的最大長度,最後一個參數就是文件指針,指向要讀取的文件。
若成功,返回 buf;若已達到文件尾端或出錯,則返回 NULL。
  • 直接I/O(二進制 I/O)
若成功,返回讀或寫的對象數。若是出錯或達到文件尾端,則此數字能夠少於 nobj。
文件 I/O 使用 read 函數從打開的文件中讀取數據。
其中 fd 就是 open 返回的文件描述符,buf用於存儲數據的目的緩衝區,而 nbytes 指定要讀取的字節數。
 
若是成功讀取,就返回讀取的字節數,如已達到文件的尾端,則返回 0。若是失敗,則返回-1。
putc,fputc,putchar,
fputs,puts,
fwrite
write
 
標準 I/O 能夠用 3 種方式進行文件寫入。
  • 每次一個字符的I/O
第一個參數是字符,第二個參數是文件指針。
putchar(c)等同於putc(stdin),putc可被實現爲宏,而fputc不能。
若成功,返回c;失敗則返回 EOF。
  • 每次一行的I/O
fputs 函數將一個 null 字節終止的字符串寫到指定的流,尾端的終止符 null不寫出。這並不必定是每次輸出一行,由於字符串不須要換行符做爲最後一個非null字節。一般,在 null 字節以前是一個換行符
puts 將一個 null 字節終止的字符串寫到標準輸出,終止符不寫出。可是,puts 隨後又將一個換行符寫到標準輸出。
若成功,返回非負值;失敗則返回 EOF。
  • 直接I/O(二進制 I/O)
若成功,返回讀或寫的對象數。若是出錯或達到文件尾端,則此數字少於 nobj。
文件 I/O 使用 write 函數向打開的文件寫數據。
其中 fd 就是文件描述符,buf是要寫入的內存數據,而 nbytes 指定要寫的字節數。
 
若是成功寫入,就返回已寫的字節數,失敗則返回-1。
隨機存取
ftell,fseek
lseek
 
標準I/O 使用 fseek 和 ftell 完成文件的隨機存取。
fseek 函數的第一個參數是文件指針,第二個參數是一個 long 類型的偏移量(offset),表示從起始點開始移動的距離。第三個參數就是用於指定起始點的模式,主要有 SEEK_SET(文件開始處)、SEEK_CUR(當前位置)、SEEK_END(文件結尾處)。
成功,返回0,出錯,返回-1。
 
ftell 函數用於返回文件的當前位置,返回類型是一個 long 類型。
成功,返回當前文件位置指示,出錯,返回-1L。
文件I/O 使用 lseek 來完成文件的隨機存取。
fd 是文件描述符,offset 是偏移量,whence 指定起始點模式,取值與fseek相同:SEEK_SET,SEEK_CUR,SEEK_END,但也能夠用整數0,1,2相應代替。
與fseek 不一樣的是,lseek有返回值,若是成功就返回指針變化前的位置,不然返回-1。
 
4、一圖泛讀 APUE 之標準 I/O 庫
 
5、strace 命令跟蹤 PHP 函數的系統調用
strace是一個可用於診斷、調試的Linux用戶空間跟蹤器,能夠用它來監控用戶空間進程和內核的交互,好比系統調用、信號傳遞、進程狀態變動等。
建立一個php文件,內容以下:
<?php
    $file = fopen("test.txt", "wr");
    fwrite($file, "test\n");
    fclose($file);
?>

執行以下命令:php

strace php open.php

能夠看到strace的結果:數組

lstat 函數返回文件的信息。
open打開文件,第二個參數是文件的打開模式,
    O_WRONLY 只讀打開,
    O_CREAT 此文件不存在則建立, 
    O_TRUNC 若是此文件存在,並且爲只讀或讀-寫成功打開,則將其長度截斷爲0。
fstat 函數得到已在文件描述符 fd 打開文件的有關信息。
lseek 函數爲一個打開的文件設置偏移量。
write 寫入內容
close 關閉文件
由此能夠看出,PHP文件函數其實就是文件I/O上的一些封裝。
相關文章
相關標籤/搜索