1. 程式人生 > >Linux系統呼叫之I/O操作

Linux系統呼叫之I/O操作

一、檔案描述符

在 Linux 的世界裡,一切裝置皆檔案。我們可以系統呼叫中 I/O 的函式(I:input,輸入;O:output,輸出),對檔案進行相應的操作( open()、close()、write() 、read() 等)。
開啟現存檔案或新建檔案時,系統(核心)會返回一個檔案描述符,檔案描述符用來指定已開啟的檔案。這個檔案描述符相當於這個已開啟檔案的標號,檔案描述符是非負整數,是檔案的標識,操作這個檔案描述符相當於操作這個描述符所指定的檔案

程式執行起來後(每個程序)都有一張檔案描述符的表,標準輸入、標準輸出、標準錯誤輸出裝置檔案被開啟,對應的檔案描述符 0、1、2 記錄在表中。程式執行起來後這三個檔案描述符是預設開啟的:

#define STDIN_FILENO  0 //標準輸入的檔案描述符
#define STDOUT_FILENO 1 //標準輸出的檔案描述符
#define STDERR_FILENO 2 //標準錯誤的檔案描述符

上面3個常量定義在/usr/include/unistd.h中。

在程式執行起來後開啟其他檔案時,系統會返回檔案描述符表中最小可用的檔案描述符,並將此檔案描述符記錄在表中。Linux 中一個程序最多隻能開啟 NR_OPEN_DEFAULT (即1024)個檔案,故當檔案不再使用時應及時呼叫 close() 函式關閉檔案。


二、常用 I/0 函式

需要的標頭檔案:

  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <fcntl.h>
  4. #include <unistd.h>

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

功能:

開啟檔案,如果檔案不存在則建立。

引數:

pathname: 檔案的路徑及檔名。

flags: 開啟檔案的行為標誌,如,以只讀方式(O_RDONLY,第一個為字母不是)開啟,以讀寫或新建新檔案的方式(O_RDWR|O_CREAT

)開啟。


mode: 這個引數,只有在檔案不存在時有效,指新建檔案時指定檔案的許可權(檔案許可權詳情,請點此連結)。

返回值:

成功:成功返回開啟的檔案描述符
失敗:-1

int close(int fd);

功能:
關閉已開啟的檔案
引數:
fd: 檔案描述符,open()的返回值
返回值:
成功:0
失敗:-1

ssize_t write(int fd, const void *addr, size_t count);

功能:
把指定數目的資料寫到檔案(fd)
引數:
fd: 檔案描述符
addr: 資料首地址
count: 寫入資料的長度(位元組),一般情況下,資料有多少,就往檔案裡寫多少,不能多也不能少
返回值:
成功:實際寫入資料的位元組個數
失敗:-1

ssize_t read(int fd, void *addr, size_t count);

功能:
把指定數目的資料讀到記憶體(緩衝區)
引數:
fd: 檔案描述符
addr: 記憶體首地址
count: 讀取的位元組個數
返回值:
成功:實際讀取到的位元組個數
失敗:-1

三、實戰篇

接下來,我們使用以上 4 個系統呼叫 I/O 函式寫一個程式,能實現像系統命令 cp 的功能:


例項程式碼如下:

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <string.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>
  7. int main(int argc, char *argv[])  
  8. {  
  9.     if((argc == 3) && (strcmp(argv[1], argv[2]) != 0))  
  10.     {// 保證有 3 個引數,而且原始檔和目的檔名字不能一樣
  11.         int fd_src, fd_dest, len;  
  12.         //只讀方式開啟原始檔
  13.         fd_src = open(argv[1], O_RDONLY);   
  14.         if(fd_src < 0)  
  15.         {  
  16.             perror("open argv[1]");  
  17.             return -1;  
  18.         }  
  19.         // 新建目的檔案
  20.         fd_dest = open(argv[2], O_WRONLY|O_CREAT, 0755);  
  21.         if(fd_dest < 0)  
  22.         {  
  23.             close(fd_src);  
  24.             perror("open argv[2]");  
  25.             return -1;  
  26.         }  
  27.         do
  28.         {  
  29.             char buf[1024] = {0};  
  30.             // 從原始檔讀取資料
  31.             len = read(fd_src, buf, sizeof(buf));  
  32.             // 把資料寫到目的檔案,注意最後一個引數,有多少寫多少
  33.             write(fd_dest, buf, len);  
  34.         }while(len > 0);  
  35.         // 關閉已開啟的檔案
  36.         close(fd_src);  
  37.         close(fd_dest);  
  38.     }  
  39.     return 0;  
  40. }  

執行結果: