Linux文件IO操作函數概述


文件概述

Linux中,一切皆文件。文件為操作系統服務和設備提供了一個簡單而一致的接口。這意味着程序完全可以像使用文件那樣使用磁盤文件、串行口、打印機和其他設備。

也就是說,大多數情況下,你只需要使用5個函數: open、close、read、write和ioctl。 例外的情況: 目錄的讀寫,網絡連接等特殊文件

 

目錄

文件通常由兩部分組成: 內容 + 屬性,即管理信息,包括文件的創建修改日期和訪問權限等。屬性均保存在 inode 節點中。inode - "索引節點",儲存文件的元信息,比如

文件的創建者、文件的創建日期、文件的長度和文件在磁盤上存放的位置等等。每個inode都有一個號碼,操作系統用inode號碼來識別不同的文件。ls -i  查看inode 號。

 目錄是用於保存其他文件的節點號和名字的文件,每個數據項為指向文件節點的鏈接。如下圖:

當文件鏈接數變為零,意味文件刪除,磁盤空間變成可用空間。

 

文件和設備

三個重要的設備文件:

/dev/console - 系統控制台。  

/dev/tty - 訪問不同的物理設備。   

/dev/null - 空設備,向所有寫這個設備的輸出都將被丟棄。

 

設備驅動程序:

操作系統的核心部分,即內核,是由一組設備驅動程序組成。他們是一組對系統硬件進行控制的底層接口,為了向用戶提供一個一致的接口,其封裝了所有與硬件相關的特性。

硬件特有功能可通過ioctl(用於I/O控制)系統調用來提供。

 /dev 目錄下的設備文件都可以被打開、讀、寫和關閉。

1)open : 打開文件或設備。

2)read : 從打開的文件或設備里讀數據。

3)write: 向文件或設備寫數據。

4)close: 關閉文件或設備。

5) ioctl:  把控制信息傳遞給設備驅動程序,每個驅動都由自己的一組 ioctl 命令。

 

 

庫函數

針對輸入輸出操作直接使用底層系統調用效率非常低,原因由如下兩點。

1)使用系統調用會影響系統性能。  

2)硬件會對底層系統調用一次所讀寫的數據塊大小做限制。磁盤:至少一個扇區512

字節,磁帶,一次 10K

 庫函數給設備和磁盤文件提供了更高層的接口,即標准函數庫。使用它你可以高效讀寫任意長度的數據塊,庫函數則在數據滿足條件后再安排系統調用。這樣極大降低了開銷。

 注:庫函數的文檔一般放在手冊的第三頁,每個庫函數有其對應的頭文件。

 

底層文件訪問

運行中的程序稱為進程,每個進程都有與之關聯的文件描述符。

 

文件描述符 - 一些小值整數,通過他們訪問打開的文件或設備。開始運行會有三個文件描述符:

1)0:   標准輸入   STDIN_FILENO

2)1:   標准輸出   STDOUT_FILENO

3)2:   標准錯誤   STDERR_FILENO

 

文件描述符的變化范圍是:0~OPEN_MAX-1 (可通過ulmit -a 查看)

 

write系統調用

作用:把緩沖區buf 的前count 個字節寫入與文件描述符 fd 相關聯的文件中。

#include <unistd.h> size_t write(int fd,const void *buf, size_t count);

描述符出錯,文件達到進程限制最大值或設備驅動程序對數據塊 長度比較敏感,該返回值可能會小於count,這並不是一個錯誤。 0 表示未寫入數據; -1 表示出錯,錯誤代號在全局變量 errno里。

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h>

int main() { const char * output = "Hello World\n"; const char * errstr = "A Write error has occurred on file descriptior !\n"; if(write(1,output,strlen(output))!=strlen(output)); write(2,errstr,strlen(errstr)); exit(0); } 

 

read系統調用

作用:作用:從與文件描述符 fd 相關聯的文件中讀取前count 個字節到緩沖區buf 中。

#include <unistd.h> size_t write(int fd,const void *buf, size_t count);

它返回實際讀入的字節數,這可能會小於請求的字節數。 0 表示未讀入任何數據,已到達了文件尾部。 -1 表示出錯,錯誤代號在全局變量 errno里。

#include <unistd.h> #include <stdlib.h>

int main() { char buffer[128]; int nread = read(0,buffer,128); if(nread == -1) write(2,"A read error has occurred\n",26); if(write(1,buffer,nread)!= nread) write(2,"A write error has occurred\n",27); }

 

 

open系統調用

作用:創建一個新的文件描述符(文件或設備)。

#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>

int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);

open 建立一條到文件或設備的訪問路徑。成功后可獲得供 read、write和其他系統調用使用的唯一的文件描述符。此文件描述符進程唯一;如果兩個程序打開同一個文件,那么,他們分別得到不同的文件描述符,並可以單獨對文件進行獨立的操作。我們可以通過文件鎖(O_EXCL或FCNTL)功能來解決這個問題。

參數說明:

pathname - 指示准備打開的文件或設備的名字;

flags    - 用於指定打開文件所采取的動作;

mode    - 用於指定創建文件的權限,O_CREATE 才使用。

flags 參數通過必需文件訪問模式 與 其他可選模式相結合的方式來指定。 首先必須指定如下文件訪問模式之一:

模     式

說    明

O_RDONLY

以只讀方式打開

O_WRONLY

以只寫方式打開

O_RDWR

以讀寫方式打開

可選模式組合:

1) O_APPEND: 把寫入數據最佳在文件的末尾。

2) O_TRUNC:  打開文件時把文件長度設置為零,丟棄已有的內容。

3) O_CREAT:   如果需要,就按參數mode 中給出的訪問模式創建文件。

4) O_EXCL:   與O_CREAT一起使用,確保創建文件的 原子操作。如果文件存在,創建 將失敗

 

訪問權限的初始:

單個權限設置     : S_I  R或W或X    USR或GRP或OTH

讀寫執行全權限 : S_I RWX             U或G或O

如: S_IRUSR    讀權限  文件屬性

   S_IRWXO   讀寫執行  其他用戶 

最終權限生成還和進程設置的umask權限掩碼有關,執行umask命令或者函數 可以改變權限。   

新文件描述符總使用未用文件描述符的最小值。如果一個文件符被關閉再次調用open ,其馬上會被重用。

 !Posix 規定了一個 creat 調用:  等同於  O_CREAT|O_WRONLY|O_TRUNC 

 

close系統調用

作用:終止文件描述符fd 和對應文件(文件或設備)的關聯。文件描述符被釋放並能夠重新使用。close 調用成功返回0,出錯返回 -1。

#include <unistd.h>
int close(int fd);

返回值: 檢查 close 調用的返回值很重要。可以檢測某些寫操作錯誤!

 

ioctl系統調用

ioctl提供了一個用於控制設備及其描述行為和配置底層的服務的接口。終端文件描述符、套接字都可以定義他們的ioctl,具體需要參考特定設備的手冊。

#include <sys/ioctl.h>

int ioctl(int d, int request, ...);

 

 

dup和dup2的系統調用

作用:提供了一種復制文件描述符的方法,是我們通過兩個或者更多不同的描述符來訪問同一個文件,主要用於多個進程間進行管道通信。

#include <unistd.h>

       int dup(int oldfd); int dup2(int oldfd, int newfd);

 

lseek系統調用

作用:

作用:lseek 對文件描述符 fd 的讀寫指針進行設置。也就是說,設置文件的下一個讀寫位置。可根據絕對位置和相對位置(當前位置或文件尾部)進行設置。

#include <sys/types.h> #include <unistd.h> off_t lseek(int fd, off_t offset, int whence);

offset 參數用來指定位置,而whence 參數定義該偏移值的用法。Whence 可取值如下:

 

1)SEEK_SET:     offset 是一個絕對位置。

2)SEEK_CUR:    offset 是相對於當前位置的一個相對位置。

3)SEEK_END:    offset 是相對於文件尾的一個相對位置。

 lseek 返回從文件頭到文件指針被設置處的字節偏移值,失敗時返回-1.

 

fstat、stat和lstat系統調用

作用:獲取文件的狀態信息,該信息將會寫入一個buf中,buf的地址會以參數的形式傳遞給fstat

#include <sys/types.h> #include <sys/stat.h> #include <unistd.h>

       int stat(const char *path, struct stat *buf); int fstat(int fd, struct stat *buf); int lstat(const char *path, struct stat *buf);

stat 和 lstat 均通過文件名查詢狀態信息,當文件名是符號鏈接時,lstat返回的時符號鏈接本身的信息,而stat 返回的時改鏈接指向的文件的信息。

struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* inode number */ mode_t st_mode; /* protection */ nlink_t st_nlink; /* number of hard links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ dev_t st_rdev; /* device ID (if special file) */ off_t st_size; /* total size, in bytes */ blksize_t st_blksize; /* blocksize for filesystem I/O */ blkcnt_t st_blocks; /* number of 512B blocks allocated */ time_t st_atime; /* time of last access */ time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last status change */ }; 

這里要特別提到的是,以上 st_mode 標志有一系列相關的宏,定義見 sys/stat.h 中

,可用來測試文件類型,如:

 

 

錯誤處理

許多系統調用和函數都會因為各種各樣的原因失敗。他們失敗時設置外部變量errno 來知名失敗原因。許多不同函數庫都把這個變量用做報告錯誤的標准方法。

注意: 程序必須在函數報告出錯 之后立刻檢查errno 變量,因為它可能馬上就被下一個函數調用所覆蓋,即使下一個函數沒有出錯,也可能會覆蓋這個變量。

常用錯誤代碼的取值和含義如下:

l   EPERM:     操作不允許

l   ENOENT:   文件或目錄不存在。

l   EINTR:     系統調用被中斷。

l   EAGAIN:    重試,下次有可能成功!

l   EBADF:     文件描述符失效或本身無效

l   EIO:        I/O錯誤。

l   EBUSY:     設備或資源忙。

l   EEXIST:     文件存在。

l   EINVL:      無效參數。

l   EMFILE:     打開的文件過多。

l   ENODEV:    設備不存在。

l   EISDIR:      是一個目錄。

l  ENOTDIR:     不是一個目錄。

 

兩個有效函數可報告出現的錯誤: strerror  和 perror。

 

strerror 函數

  作用:把錯誤代號映射成一個字符串,該字符串對發生的錯誤類型進行說明。

 

#include <string.h>                                                     
   char *strerror(int errnum); int strerror_r(int errnum, char *buf, size_t buflen);

perror函數

  作用:perror 函數也把errno 變量中報告的當前錯誤映射成一個字符串,並把它輸出到標准錯誤輸出流。

 

perror(“test”);                                                            

結果:

Test: Too many open files     

 

 

 

 

 

 

         


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM