本頁使用了標題或全文手工轉換

檔案描述符

維基百科,自由的百科全書
前往: 導覽搜尋

檔案描述符File descriptor)是電腦科學中的一個術語,是一個用於表述指向檔案的參照的抽象化概念。

概要[編輯]

檔案描述符在形式上是一個非負整數。實際上,它是一個索引值,指向內核為每一個行程所維護的該行程開啟檔案的記錄表。當程式開啟一個現有檔案或者建立一個新檔案時,內核向行程返回一個檔案描述符。在程式設計中,一些涉及底層的程式編寫往往會圍繞著檔案描述符展開。但是檔案描述符這一概念往往只適用於UNIXLinux這樣的作業系統。

每個Unix行程(除了可能的守護行程)應均有三個標準的POSIX檔案描述符,對應於三個標準流:

整數值 名稱 <unistd.h>符號常量[1] <stdio.h>檔案流[2]
0 Standard input STDIN_FILENO stdin
1 Standard output STDOUT_FILENO stdout
2 Standard error STDERR_FILENO stderr

優點[編輯]

檔案描述符的優點主要有兩個:

  • 基於檔案描述符的I/O操作相容POSIX標準。
  • 在UNIX、Linux的系統呼叫中,大量的系統呼叫都是依賴於檔案描述符。

例如,下面的代碼就示範了如何基於檔案描述符來讀取當前目錄下的一個指定檔案,並把檔案內容列印至Console中。

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

int main (void){
    int fd;
    int numbytes;
    char path[] = "file";
    char buf[256];

    /*
     * O_CREAT:如果文件不存在则创建
     * O_RDONLY:以只读模式打开文件
     */
    fd = open(path, O_CREAT | O_RDONLY, 0644);
    if(fd < 0){
        perror("open()");
        exit(EXIT_FAILURE);
    }

    memset(buf, 0x00, 256);
    while((numbytes = read(fd, buf, 255)) > 0){
        printf("%d bytes read: %s", numbytes, buf);
        memset(buf, 0x00, 256);
    }
    close (fd);
    exit(EXIT_SUCCESS);
}

此外,在Linux系列的作業系統上,由於Linux的設計思想便是把一切裝置都視作檔案。因此,檔案描述符為在該系列平台上進行裝置相關的編程實際上提供了一個統一的方法。

缺點[編輯]

檔案描述符的概念存在兩大缺點:

  • 在非UNIX/Linux 作業系統上(如Windows),無法基於這一概念進行編程——事實上,Windows下的檔案描述符和號誌互斥鎖內核物件一樣都記作HANDLE。
  • 由於檔案描述符在形式上不過是個整數,當代碼量增大時,會使編程者難以分清哪些整數意味著資料,哪些意味著檔案描述符。因此,完成的代碼可讀性也就會變得很差,這一點一般通過消除魔術數字來解決。

其他[編輯]

  • 對於ANSI C規範中定義的標準庫的檔案I/O操作。ANSI C規範給出了一個解決方法,就是使用FILE結構體的指標。事實上,UNIX/Linux平台上的FILE結構體的實現中往往都是封裝了檔案描述符變數在其中。
  • 在UNIX/Linux平台上,對於控制台(Console)的標準輸入標準輸出標準錯誤輸出也對應了三個檔案描述符。它們分別是0,1,2。在實際編程中,如果要操作這三個檔案描述符時,建議使用<unistd.h>表頭檔中定義的三個宏來表示:STDIN_FILENO, STDOUT_FILENO以及STDERR_FILENO。
  • 對於一個行程而言,檔案描述符的變化範圍為0~OPEN_MAX[3].

與檔案描述符相關的操作[編輯]

檔案描述符的生成[編輯]

  • open(), open64(), creat(), creat64()
  • socket()
  • socketpair()
  • pipe()

與單一檔案描述符相關的操作[編輯]

  • read(), write()
  • recv(), send()
  • recvmsg(), sendmsg()
  • sendfile()
  • lseek(), lseek64()
  • fstat(), fstat64()
  • fchmod()
  • fchown()

與複數檔案描述符相關的操作[編輯]

  • select(), pselect()
  • poll(),epoll()

與檔案描述符表相關的操作[編輯]

  • close()
  • dup()
  • dup2()
  • fcntl (F_DUPFD)
  • fcntl (F_GETFD and F_SETFD)

改變行程狀態的操作[編輯]

  • fchdir()
  • mmap()

與檔案加鎖的操作[編輯]

  • flock()
  • fcntl (F_GETLK, F_SETLK and F_SETLKW)
  • lockf()

與通訊端相關的操作[編輯]

  • connect()
  • bind()
  • listen()
  • accept()
  • getsockname()
  • getpeername()
  • getsockopt(), setsockopt()
  • shutdown()

其他[編輯]

  • ioctl()

注釋[編輯]

  1. ^ The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition. 
  2. ^ The IEEE and The Open Group. <stdio.h>. The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition. [May 31, 2014]. 
  3. ^ OPEN_MAX定義在表頭檔"limits.h"中