老三樣,學(xué)習(xí)一個(gè)新概念之前,先提出三個(gè)問(wèn)題:
- 它是啥
- 它干哈用的
- 咋用啊這玩意
文件描述符的概念
文件描述符在形式上是一個(gè)非負(fù)整數(shù)。實(shí)際上,它是一個(gè)索引值,指向內(nèi)核為每一個(gè)進(jìn)程所維護(hù)的該進(jìn)程打開(kāi)的文件的記錄表。當(dāng)程序打開(kāi)一個(gè)文件時(shí),內(nèi)核向進(jìn)程返回一個(gè)文件描述符。
哈哈哈哈,懵不懵?這玩意你們能看懂嗎?這是維基百科里的標(biāo)準(zhǔn)解釋。
再了解文件描述符的概念之前,咱們先了解下應(yīng)用程序訪問(wèn)系統(tǒng)文件的流程。
文件是存儲(chǔ)在磁盤(pán)里的,磁盤(pán)是PC硬件,應(yīng)用程序想要訪問(wèn)硬件系統(tǒng)是不能直接訪問(wèn)的,必須發(fā)起系統(tǒng)調(diào)用,由系統(tǒng)內(nèi)核來(lái)發(fā)起調(diào)用讀寫(xiě)文件。
現(xiàn)代操作系統(tǒng),將內(nèi)存劃分為兩個(gè)部分,一個(gè)是用戶空間,另一個(gè)是內(nèi)核空間。應(yīng)用程序在用戶空間內(nèi)運(yùn)行,系統(tǒng)內(nèi)核在內(nèi)核空間中運(yùn)行。用戶空間的應(yīng)用程序沒(méi)有權(quán)限直接訪問(wèn)硬件資源,但是系統(tǒng)內(nèi)核可以,比如讀寫(xiě)文件、讀寫(xiě)網(wǎng)卡。用戶程序想要訪問(wèn)硬件資源,必須發(fā)起系統(tǒng)調(diào)用(system call)。內(nèi)核收到系統(tǒng)調(diào)用后,執(zhí)行并將結(jié)果返回給應(yīng)用程序。
一個(gè)用戶程序讀取硬盤(pán)文件的流程如下:

上面簡(jiǎn)單介紹了用戶空間和內(nèi)核空間,這對(duì)于理解fd有很大幫助。 fd的存在,就是因?yàn)橛脩舫绦驘o(wú)法直接訪問(wèn)硬件,因此當(dāng)應(yīng)用程序發(fā)起系統(tǒng)調(diào)用打開(kāi)一個(gè)文件后,必須有一個(gè)東西標(biāo)識(shí)著這個(gè)文件,這個(gè)標(biāo)識(shí)就是fd。
三張表
file descriptors: 由用戶程序維護(hù)的記錄表,記錄的是該用戶程序打開(kāi)的所有的文件的fd。每個(gè)進(jìn)程會(huì)預(yù)留三個(gè)默認(rèn)的fd:stdin(0)、 stdout(1)、stderr(2)。
file table:該表是全局唯一的,由系統(tǒng)內(nèi)核維護(hù),記錄了所有進(jìn)程打開(kāi)的文件的狀態(tài)、偏移量、訪問(wèn)模式(可讀寫(xiě))、文件類(lèi)型、該文件對(duì)應(yīng)的inode對(duì)象引用等
Inode table: 全局唯一的表,是硬盤(pán)存儲(chǔ)的文件的元數(shù)據(jù)的集合

如果不清楚Inode Table是啥,可以看下之前的這篇文章:徹底搞懂硬鏈接和軟鏈接

三張表的映射關(guān)系如上圖。
結(jié)合這三張表,應(yīng)用程序讀一個(gè)硬盤(pán)文件的流程如下:
*當(dāng)用戶程序需要讀寫(xiě)一個(gè)硬盤(pán)文件時(shí), 首先調(diào)用Open()方法打開(kāi)文件,此時(shí)會(huì)發(fā)起系統(tǒng)調(diào)用;
*內(nèi)核收到調(diào)用請(qǐng)求會(huì)根據(jù)文件名找到對(duì)應(yīng)文件的inode編碼,然后根據(jù)inode編碼去inode table找到對(duì)應(yīng)編碼的inode元數(shù)據(jù);
*然后內(nèi)核會(huì)根據(jù)元數(shù)據(jù)信息創(chuàng)建一個(gè)包含文件信息的entry插入到file table中,并向應(yīng)用程序返回file descriptor;
*應(yīng)用程序?qū)d插入到file descriptors表中,到此時(shí)應(yīng)用程序拿到了該文件的fd;
*當(dāng)應(yīng)用程序read()時(shí),發(fā)起系統(tǒng)調(diào)用,將fd傳給內(nèi)核;
*內(nèi)核根據(jù)fd以及這三張表的映射關(guān)系,找到對(duì)應(yīng)的inode元數(shù)據(jù);
*內(nèi)核根據(jù)元數(shù)據(jù)信息向磁盤(pán)發(fā)起讀取請(qǐng)求,將數(shù)據(jù)寫(xiě)入內(nèi)核緩沖區(qū)(內(nèi)核空間);
*內(nèi)核將內(nèi)核緩沖區(qū)的數(shù)據(jù)復(fù)制到用戶進(jìn)程的用戶緩沖區(qū)(用戶空間);
回答最開(kāi)始提出的三個(gè)問(wèn)題:
fd是啥?
fd是系統(tǒng)維護(hù)的file table表的某一項(xiàng)entry的指針,應(yīng)用程序通過(guò)它能讀寫(xiě)硬盤(pán)里文件。
fd有啥用?
應(yīng)用程序用它來(lái)跟內(nèi)核打交道,讓內(nèi)核以fd定位應(yīng)用程序所需訪問(wèn)的文件并幫忙讀寫(xiě)數(shù)據(jù)
fd 咋用?
程序員絕大多數(shù)情況下不會(huì)直接使用它,系統(tǒng)底層已經(jīng)幫我們封裝好了接口,我們只需要調(diào)用類(lèi)似Open()、Read()、Write()等接口方法就可以了。