linux系統程式設計之檔案與IO(一):檔案描述符、open,close

mickole發表於2013-07-09
  1. 什麼是IO?
  • 輸入/輸出是主存和外部裝置之間拷貝資料的過程

          裝置->記憶體(輸入操作)

           記憶體->裝置(輸出操作)

  • 高階I/O

          ANSI C提供的標準I/O庫稱為高階I/O,通常也稱為帶緩衝的I/O

  • 低階I/O

          通常也稱為不帶緩衝的I/O

2. 檔案描述符:fd

  • 對於Linux而言,所有對裝置或檔案的操作都是通過檔案描述符進行的。
  • 當開啟或者建立一個檔案的時候,核心向程式返回一個檔案描述符(非負整數)。後續對檔案的操作只需通過該檔案描述符,核心記錄有關這個開啟檔案的資訊。
  • 一個程式啟動時,預設開啟了3個檔案,標準輸入、標準輸出、標準錯誤,對應檔案描述符是0(STDIN_FILENO)、1(STDOUT_FILENO)、2(STDERR_FILENO),這些常量定義在unistd.h標頭檔案中。C庫函式中與之對應的是:stdin,stdout,stderr,不過這三個是FILE指標型別。

3.檔案描述符與檔案指標相互轉換

可以通過以下兩個函式實現:

  • fileno:將檔案指標轉換為檔案描述符

            #include <stdio.h>

            int fileno(FILE *stream)

測試程式:

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

int main(void)
{
    printf("fileno(stdin) = %d\n", fileno(stdin));
    printf("fileno(stdout) = %d\n", fileno(stdout));
    printf("fileno(stderr) = %d\n", fileno(stderr));
    return 0;
}
測試結果:
QQ截圖20130710112307
  • fdopen:將檔案描述符轉換為檔案指標

#include <stdio.h>

        FILE *fdopen(int fd, const char *mode)    //mode :r,w,r+,w+,a,a+

4.檔案系統呼叫

  • open系統呼叫

有幾種方法可以獲得允許訪問檔案的檔案描述符。最常用的是使用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);

引數

path :檔案的名稱,可以包含(絕對和相對)路徑

flags:檔案開啟模式

mode:用來規定對該檔案的所有者,檔案的使用者組及系 統中其他使用者的訪問許可權

返回值

開啟成功,返回檔案描述符;

開啟失敗,返回-1

檔案開啟方式:

 

QQ截圖20130709224005

O_EXCL表示:當O_EXCL|O_CREAT時,若檔案存在,則開啟失敗,不存在,則開啟成功

訪問許可權:

QQ截圖20130709224029

open系統呼叫的幾點說明:

可以利用按位邏輯加(bitwise-OR)(|)對開啟方式的標誌值進行組合。

如開啟一個新檔案:

#define NEWFILE  (O_WRONLY|O_CREAT|O_TRUNC)

對訪問許可權位進行訪問所用到的識別符號,均可以通過

#include <sys/stat.h> 訪問到,同樣可以通過|運算來對訪問許可權進行組合也可以直接給出數字表示如0655

#define MODE755 (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)

注:檔案的訪問許可權是根據:umask&~mode得出來的,例如umask=0022,mode = 0655 則訪問許可權為:644

測試程式:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>


#define ERR_EXIT(m) \
    do \
    { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

int main(void)
{
    umask(0);
    int fd;
    fd = open("test.txt", O_WRONLY | O_CREAT, 0666);
    if (fd == -1)
        ERR_EXIT("open error");

    printf("open succ\n");
    return 0;
}

測試結果一:採用預設的umask值

 QQ截圖20130710113500

測試結果二:重新設定umask值

QQ截圖20130710113508

    • close系統呼叫

為了重新利用檔案描述符,用close()系統呼叫釋放開啟的檔案描述符

函式原型:

#include <unistd.h>

int close(int fd);

函式引數:

-fd :要關閉的檔案的檔案描述符

返回值

如果出現錯誤,返回-1

呼叫成功返回0

注:若沒有顯示呼叫close(),當程式退出時也會關閉檔案

    • creat系統呼叫

為了維持與早期的UNIX系統的向後相容性,Linux也提供可選的建立檔案的系統呼叫,它稱為creat()。現代的linux核心很少採用creat建立檔案,因為open可以完成建立功能

函式原型:

int creat(const char *path, mode_t mode);

引數

path :檔案的名稱,可以包含(絕對和相對)路徑

mode: 用來規定對該檔案的所有者,檔案的使用者組及系 統中其他使用者的訪問許可權

返回值

開啟成功,返回檔案描述符;

開啟失敗,返回-1

 

       在UNIX的早期版本中,open()系統呼叫僅僅存在兩個引數的形式。如檔案不存在,它就不能開啟這些檔案。檔案的建立則由單獨的系統呼叫creat()完成。在Linux及所有UNIX的近代版本中,creat()系統呼叫是多餘的。

creat()呼叫

fd = creat(file, mode);

完全等價於近代的open()呼叫

fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, mode);

相關文章