Linux標準IO庫簡介

  • 爲什麼要設計標準I/O庫?
    ➢ 直接使用API進行文件訪問時,需要考慮許多細節問題,例如:read、write時,緩衝區的大小該如何確定,才能使效率最優。
    ➢ read和write等底層系統調用函數進行輸入輸出時,在用戶態和內核態之間來回切換,每次讀出或寫入的數據量較少,導致頻繁的I/O操作,增加了系統開銷。
  • 標準I/O庫是ANSI C規範的一部分,函數原型在文件stdio.h中定義,對底層I/O系統調用進行了封裝,爲程序員提供了帶有格式轉換功能的輸入輸出操作,並在用戶空間增加了緩衝區管理。
  • 文件IO和標準IO區別:
  1. 文件I/O:文件I/O稱之爲不帶緩存的IO(unbuffered I/O)。不帶緩存指的是每個read,write都調用內核中的一個系統調用。也就是一般所說的低級I/O——操作系統提供的基本IO服務,與os綁定,特定於linix或unix平臺。
  2. 標準I/O:標準I/O是ANSI C建立的一個標準I/O模型,是一個標準函數包和stdio.h頭文件中的定義,具有一定的可移植性。標準I/O庫處理很多細節。例如緩存分配,以優化長度執行I/O等。標準的I/O提供了三種類型的緩存。
    (1)全緩存:當填滿標準I/O緩存後才進行實際的I/O操作。
    (2)行緩存:當輸入或輸出中遇到新行符時,標準I/O庫執行I/O操作。
    (3)不帶緩存:stderr就是了。
  3. 文件I/O 又稱爲低級磁盤I/O,遵循POSIX相關標準。任何兼容POSIX標準的操作系統上都支持文件I/O。
  4. 標準I/O被稱爲高級磁盤I/O,遵循ANSI C相關標準。只要開發環境中有標準I/O庫,標準I/O就可以使用。(Linux 中使用的是GLIBC,它是標準C庫的超集。不僅包含ANSI C中定義的函數,還包括POSIX標準中定義的函數。因此,Linux 下既可以使用標準I/O,也可以使用文件I/O)。
  5. 通過文件I/O讀寫文件時,每次操作都會執行相關係統調用。這樣處理的好處是直接讀寫實際文件,壞處是頻繁的系統調用會增加系統開銷,標準I/O可以看成是在文件I/O的基礎上封裝了緩衝機制。先讀寫緩衝區,必要時再訪問實際文件,從而減少了系統調用的次數。
  6. 文件I/O中用文件描述符表現一個打開的文件,可以訪問不同類型的文件如普通文件、設備文件和管道文件等。而標準I/O中用FILE(流)表示一個打開的文件,通常只用來訪問普通文件。
  • 標準IO庫
  • 分離了應用程序空間和實際的物理設備
  • 減少了直接讀盤次數,提高性能
    ➢ 讀取前查看是否已存在頁緩存中,如果已經存放在了頁緩存中,數據立即返回給應用程序
    ➢ 寫數據前先寫到頁緩存中,如果用戶採用的是同步寫機制( synchronous writes ), 那麼數據會立即被寫回到磁盤上,應用程序會一直等到數據被寫完爲止;如果用戶採用的是延遲寫機制( deferred writes ),那麼應用程序就完全不需要等到數據全部被寫回到磁盤,數據只要被寫到頁緩存中去就可以了。
  • 異步緩存和延遲寫機制一樣,不等數據全部寫回到磁盤,數據只要寫到頁緩存中即可,不同的是當數據全部寫到磁盤上後,異步機制會通知給應用程序,延遲寫機制不會。

fopen函數

  • fopen函數功能
    打開一個指定文件
  • 函數原型
    FILE *fopen(const char *restrict pathname, const char *restrict type);
  • 參數
    pathname:要打開的文件名
    type:指定文件的讀、寫方式
  • type 說明:
  1. r或rb 爲讀而打開
  2. w或wb 使文件長度爲0,或爲寫而創建
  3. a或ab 添加;爲在文件尾寫而打開,或爲寫而創建
  4. r+或r+b或rb+ 爲讀和寫而打開
  5. w+或w+b或wb+ 使文件長度爲0,或爲讀和寫而打開
  6. a+或a+b或ab+ 爲在文件尾讀和寫而打開或創建
限制 r w a r+ w+ a+
文件必須存在
刪除文件以前內容
流可以讀
流可以寫
流只在尾端處寫

setbuf和setvbuf函數

  • setbuf和setvbuf函數功能
    打開和關閉緩衝機制
  • 函數原型
    void setbuf(FILE *steam, char *buf);
    void setvbuf(FILE *steam, char *buf, int mode, size_t size);
函數 mode buf 緩存及長度 緩存的類型
setbuf nonnull 長度爲BUFSIZ的用戶緩存 全緩存
setbuf NULL (無緩存) 不帶緩存
setvbuf _IOFBF nonnull 長度爲size的用戶緩存 全緩存
setvbuf _IOFBF NULL 合適長度的系統緩存 全緩存
setvbuf _IOLBF nonnull 長度爲size的用戶緩存 行緩存
setvbuf _IOLBF NULL 合適長度的系統緩存 行緩存
setvbuf _IONBF 忽略 無緩存 不帶緩存

fdopen函數

  • fdopen函數功能
    取一個現存的文件描述符,並使一個標準I/O流與該描述符相結合
  • 頭文件
    #include<stdio.h>
  • 函數原型
    FILE *fdopen(int fd, const char *type);
  • fdopen常用於由創建管道及網絡通信通道函數返回的描述符。
    ➢ 這些特殊類型的文件,不能用fopen打開
    ➢ 因此必須先調用設備專用函數以獲得一個文件描述符,然後再用fdopen使一個標準I/O流與該描述符相關聯
  • 對於fdopen函數,type參數的意義稍有區別
    ➢ 因爲該描述符已被打開,所以fdopen爲寫而打開並不截短該文件
    ➢ 不能用於創建該文件(因爲如若一個描述符引用一個文件,則該文件一定已經存在)
Type值 操作文件類型 是否新建文件 是否清空原文件 可讀 可寫 讀寫開始位置
r 文本文件 NO NO YES NO 文件開頭
r+ 文本文件 YES NO YES YES 文件開頭
w 文本文件 YES YES NO YES 文件開頭
w+ 文本文件 YES YES YES YES 文件開頭
a 文本文件 NO YES NO YES 文件結尾
a+ 文本文件 NO YES YES YES 文件結尾
rb 二進制文件 NO NO YES NO 文件開頭
r+b或rb+ 二進制文件 YES NO YES YES 文件開頭
wb 二進制文件 YES YES NO YES 文件開頭
w+b或wb+ 二進制文件 YES YES YES YES 文件開頭
ab 二進制文件 NO YES NO YES 文件結尾
a+b或ab+ 二進制文件 NO YES YES YES 文件結尾
FILE *fp;
int fd;
if ((fp = fopen("hello.txt", "w+")) == NULL) {
printf("fopen file error\n");
return 0;}
fprintf(fp, "hello word\n");
fclose(fp);
if ((fd = open("hello.txt", O_RDWR)) == -1) {
printf("open file fail\n");
return 0;}
if ((fp = fdopen(fd, "a+")) == NULL) {
printf("fdopen open\n");
return 0;
}
fprintf(fp, "linux c program");
fclose(fp);
      
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章