1. 程式人生 > >檔案描述符fd和檔案指標File* fp的區別和轉換

檔案描述符fd和檔案指標File* fp的區別和轉換

在linux系統中把裝置和普通檔案也都看做是檔案,要對檔案進行操作就必須先開啟檔案,開啟檔案後會得到一個檔案描述符,它是一個很小的正整數,是一個索引值。
核心會為每一個執行中的程序在程序控制塊pcb中維護一個開啟檔案的記錄表,每一個表項都有一個指標指向開啟的檔案,上邊的索引值是記錄表的索引值。
檔案描述符的優點:相容POSIX標準,許多系統呼叫都依賴於它;缺點是不能移植到unix之外的系統上去。
檔案指標:c語言中使用的是檔案指標而不是檔案描述符來作為I/O的控制代碼,檔案指標指向程序的使用者空間中一個FILE結構的資料結構,FILE結構裡主要包括一個I/O緩衝區和一個檔案描述符,而檔案描述符值是檔案描述符表中的一個索引,從某種意義上將檔案指標就是控制代碼的控制代碼(在Window中檔案描述符被稱為檔案控制代碼)。
檔案指標的優點:是c語言中的通用格式,便於移植。
既然FILE結構中含有檔案描述符,那麼可以使用fopen來獲得檔案指標,然後從檔案指標獲取檔案描述符,檔案描述符應該是唯一的,而檔案指標卻不是唯一的,但指向的物件是唯一的。

1.檔案描述符fd的定義:檔案描述符在形式上是一個非負整數。實際上,它是一個索引值,指向核心為每一個程序所維護的該程序開啟檔案的記錄表。當程式開啟一個現有檔案或者建立一個新檔案時,核心向程序返回一個檔案描述符。在程式設計中,一些涉及底層的程式編寫往往會圍繞著檔案描述符展開。但是檔案描述符這一概念往往只適用於UNIX、Linux這樣的作業系統
2.檔案指標FILE定義說明檔案指標的一般形式為:
FILE *指標變數識別符號;
其中FILE應為大寫,它實際上是由系統定義的一個結構,該結構中含有檔名、檔案狀態和檔案當前位置等資訊。在編寫源程式時不必關心FILE結構的細節。
在使用檔案時,需要在記憶體中為其分配空間,用來存放檔案的基本資訊,給結構體型別是由系統定義的,

C語言規定該型別為FILE型,其宣告如下:

typedef struct
{
short level;
unsigned flags;
char fd;
unsigned char hold;
short bsize;
unsigned char *buffer;
unsigned ar *curp;
unsigned istemp;
short token;
}FILE;

例如:
FILE *fp;
表示fp是指向FILE結構的指標變數,通過fp即可找存放某個檔案資訊的結構變數,然後按結構變數提供的資訊找到該檔案,實施對檔案的操作。習慣上也籠統地把fp稱為指向一個檔案的指標。

3.fd和FILE*的關係
簡單來說 FILE*中的內容包括檔案描述符和緩衝區。
使用fopen,fclose,fread,fwrite對檔案進行操作,他們屬於C庫函式,在lib層中。返回值為FILE*。FILE*為檔案指標。
檔案指標是指向一個FILE的結構體,這個結構體裡包括一個檔案描述符和一個I/O緩衝區。檔案描述符用於C標準的IO庫呼叫中,用於標識檔案。
系統呼叫介面為:open/close/read/write
他們的返回值為檔案描述符(fb),型別為int.
檔案描述符就是open檔案時產生的一個很小的正整數,是一個索引值,它用於UNIX系統中,用於標識檔案。核心會為每一個執行中的程序在程序控制塊PCB中維護一個開啟檔案的記錄表,也就是檔案物件表,每一個表項都有一個指標指向開啟的檔案,上邊的索引值就是記錄表的索引值。
開啟一個程序後,要開啟預設的輸出輸入流,他們分別為:stderr,stdin , stdout.對應的檔案描述符為0,1,2。
這裡寫圖片描述

fd轉換為fp
int main(int argc, char *argv[])
{
    FILE *fp = NULL;
    fp  = fopen("/home/super_bert/test.dat", "r");    /*得到檔案指標*/
    if (fp == NULL)
    {
        perror("open file error.");
        exit(1);
    }
    else
    {
        printf("open file successfully...\n");
    }
    int fd;
    fd = fileno(fp);    /*檔案指標轉換為檔案描述符*/
    if (-1 == fd)
    {
        perror("fp to fd error.");
    }
    else
    {
        printf("transform successfully...\n")
        exit(1);
    }
    return 0;
}

fp轉換為fd

int main(int argc, char *argv[])
{
    int  fd;
    fd = open("/home/super_bert/test.dat", O_CREAT|O_RDWR, 0666);    /*得到檔案描述符*/
    if ( -1 == fd )
    {
        perror("open file error.");
        exit(1);
    }
    else
    {
        printf("open file successfully...\n");
    }
    FILE *fp = NULL;
    fp = fdopen(fd, "r");       /*檔案描述符轉換為檔案指標*/
    if (NULL == fp)
    {
        perror("fd to fp error.");
    }
    else
    {
        printf("transform successfully...\n");
        exit(1);
    }
    return 0;
}