文件描述符
當應用程序請求打開或者操作文件時,操作系統為應用程序設置一張文件列表,具體的實現形式此處不深入說明
操作系統會提供給你一個非負整數,作為一個索引號,它的作用就像地址或者說指針或者說偏移量
這個索引號就用來定位文件數據在內存中的位置.
這個概念在類Unix系統叫做文件描述符, linux把所有東西都被看成是文件,比如文件、目錄、進程、網絡socket、各種硬件設備等
這個概念在Windows下 稱之為句柄, 句柄是Windows下各種對象的標識符, 比如文件、資源、菜單、光標、位圖等
那么,現在你應該可以理解文件描述符的含義了
文件描述符 之於文件系統(操作系統中的一切都是文件描述符 可以使用文件描述符描述任何一個資源對象
就如同Class 之於java語言一樣(java中一切都是類,都是一個Class的實例,任何一個類都用Class對象的實例來描述
|
Java中使用FileDescriptor 來抽象文件描述符這一概念
package java.io;
對於FileInputStream/FileOutputStream/RandomAccessFile,使用handle來表示底層的文件句柄
對於ServerSocket/Socket,使用fd來表示底層的文件句柄
FileDescriptor的fd和handle的無效值是-1
看下API的描述:
文件描述符類的實例用作與基礎機器有關的某種結構的不透明句柄
該結構表示開放文件、開放套接字或者字節的另一個源或接收者。
文件描述符的主要實際用途是創建一個包含該結構的 FileInputStream 或 FileOutputStream。
應用程序不應創建自己的文件描述符。
|
其實說白了,就是文件描述符的實例,就是用來表示文件的一個指針/索引. 操作系統通過這個值與應用程序交互
如同你的電話號碼一樣,在很多場景,他就相當於你, 雖然,他完全不是你,
比如朋友想找你聊天,有人托你辦事,保險公司推銷等等,通過電話都可以定位到你
而且,你自己能造一個電話號碼么?顯然不行,必須是運營商提供給你的
我們的文件描述符,也是如此,應用程序不應該創建自己的文件描述符
他的構造方法,只能創建一個無效的文件描述符
不應該創建自己的文件描述符,可以直接理解為:
這東西是底層實現的內容,操作系統來傳遞給你
而且,對於文件的其他的一些操作,最底層的實現也仍舊是操作系統來搞
這就相當於操作系統給你的一個指針,鑰匙
你需要服務的時候,拿給操作系統即可,具體到底怎么玩,你管不上,也管不了
想要理解文件描述符只需要理解,文件的抽象概念是操作系統負責管理維護的
應用程序都是在請求操作系統幫忙,JVM也就是個應用程序
不管那個位置到底存放的是什么,對於應用程序來說就是一個描述符
操作系統提供了一致性的接口訪問途徑,就是通過這個描述符
描述符背后到底是什么,操作系統屏蔽了這些東西
這樣子的實現,對應用程序程序員來說,就是不需要在關注他到底是個什東西,操作系統來搞定
FileDescriptor中的三個描述符
FileDescriptor 內置了三個文件描述符 分別是 in out err
類型是FileDescriptor 這是java層面的描述
具體的值是 0 1 2 ,這是操作系統層面的描述
在linux 中, 每個進程啟動時都打開3個文件(linux 中一切都是文件):
* 標准輸入 0
* 標准輸出 1
* 標准錯誤 2
三個描述符,通過調用私有方法 standardStream進行創建初始化
創建一個FileDescriptor 並且,設置他的handle值
內部的set(fd)是一個本地方法
說白了,就是通過調用本地方法,獲得操作系統對標准輸入/輸出/錯誤的三個文件描述符
|
注釋中也說的很清楚,文件描述符一般不直接使用 通過使用System.in System.out System.err |
文件描述符在System類中的應用
在System 中 in out err 都是 final static的
|
標准的輸入輸出是共享,但是java是多線程的
因此它們必須受到特別的處理,在系統初始化完成之前,線程嚴禁使用這幾個特殊對象;
又因為這些對象都是靜態的,因此java的類加載機制會在System類加載的時候就會初始化,這就造成了一對矛盾;
為解決這對矛盾,System在加載是將它們初始化為null,等加在完成后,通過 initializeSystemClass
|
System中in out err中的定義部分,全都是final static
注釋中也很明確的說明了 將會調用 initializeSystemClass 進行部分初始化工作
initializeSystemClass 方法的關鍵部位 以及 本地的setIn0 setOut0 setErr0
|
initializeSystemClass 方法對於這塊來說,主要就是
使用三個文件描述符 創建了 FileInputStream 以及 FileOutputStream
對於Out以及Err又根據encoding 轉換為PrintStream
然后通過本地方法進行設置
|
所以說,那三個專門的文件描述符一般不直接使用 取而代之的則是使用文件描述符 初始化設置過的流對象 |
應用程序不創建文件描述符, 都是由系統調用, 也就是本地方法來操作的
應用程序只是獲得, 然后使用, 所謂使用,最終也還是需要借助於操作系統
是應用程序 操作文件 時 與操作系統進行交互時,必須的數據項
|