[一]JavaIO之FileDescriptor文件描述符

文件描述符

當應用程序請求打開或者操作文件時,操作系統爲應用程序設置一張文件列表,具體的實現形式此處不深入說明
操作系統會提供給你一個非負整數,作爲一個索引號,它的作用就像地址或者說指針或者說偏移量
這個索引號就用來定位文件數據在內存中的位置.
這個概念在類Unix系統叫做文件描述符, linux把所有東西都被看成是文件,比如文件、目錄、進程、網絡socket、各種硬件設備等
這個概念在Windows下 稱之爲句柄, 句柄是Windows下各種對象的標識符, 比如文件、資源、菜單、光標、位圖等
那麼,現在你應該可以理解文件描述符的含義了

文件描述符  之於文件系統(操作系統中的一切都是文件描述符 可以使用文件描述符描述任何一個資源對象
就如同Class 之於java語言一樣(java中一切都是類,都是一個Class的實例,任何一個類都用Class對象的實例來描述

Java中使用FileDescriptor 來抽象文件描述符這一概念
package java.io;
image_5b923c62_6c7f
對於FileInputStream/FileOutputStream/RandomAccessFile,使用handle來表示底層的文件句柄
對於ServerSocket/Socket,使用fd來表示底層的文件句柄
FileDescriptor的fd和handle的無效值是-1


看下API的描述:
文件描述符類的實例用作與基礎機器有關的某種結構的不透明句柄
該結構表示開放文件、開放套接字或者字節的另一個源或接收者。
文件描述符的主要實際用途是創建一個包含該結構的 FileInputStream 或 FileOutputStream。
 
應用程序不應創建自己的文件描述符。 

其實說白了,就是文件描述符的實例,就是用來表示文件的一個指針/索引. 操作系統通過這個值與應用程序交互
如同你的電話號碼一樣,在很多場景,他就相當於你,   雖然,他完全不是你,
比如朋友想找你聊天,有人託你辦事,保險公司推銷等等,通過電話都可以定位到你
 
而且,你自己能造一個電話號碼麼?顯然不行,必須是運營商提供給你的
我們的文件描述符,也是如此,應用程序不應該創建自己的文件描述符
他的構造方法,只能創建一個無效的文件描述符

不應該創建自己的文件描述符,可以直接理解爲:
這東西是底層實現的內容,操作系統來傳遞給你
而且,對於文件的其他的一些操作,最底層的實現也仍舊是操作系統來搞
這就相當於操作系統給你的一個指針,鑰匙
你需要服務的時候,拿給操作系統即可,具體到底怎麼玩,你管不上,也管不了
 
想要理解文件描述符只需要理解,文件的抽象概念是操作系統負責管理維護的
應用程序都是在請求操作系統幫忙,JVM也就是個應用程序
不管那個位置到底存放的是什麼,對於應用程序來說就是一個描述符
操作系統提供了一致性的接口訪問途徑,就是通過這個描述符
描述符背後到底是什麼,操作系統屏蔽了這些東西
這樣子的實現,對應用程序程序員來說,就是不需要在關注他到底是個什東西,操作系統來搞定
 
image_5b923c62_27aa
 

FileDescriptor中的三個描述符

FileDescriptor 內置了三個文件描述符 分別是  in   out  err
類型是FileDescriptor  這是java層面的描述
具體的值是 0  1   2  ,這是操作系統層面的描述
 
在linux 中, 每個進程啓動時都打開3個文件(linux 中一切都是文件): 
* 標準輸入  0
* 標準輸出  1
* 標準錯誤  2
 
三個描述符,通過調用私有方法 standardStream進行創建初始化
創建一個FileDescriptor 並且,設置他的handle值
內部的set(fd)是一個本地方法
說白了,就是通過調用本地方法,獲得操作系統對標準輸入/輸出/錯誤的三個文件描述符
 
image_5b923c63_6b43
 
 
image_5b923c63_409e
 
註釋中也說的很清楚,文件描述符一般不直接使用
通過使用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  進行部分初始化工作
 
image_5b923c63_21ce
 
initializeSystemClass 方法的關鍵部位 以及 本地的setIn0 setOut0 setErr0
initializeSystemClass 方法對於這塊來說,主要就是
使用三個文件描述符  創建了 FileInputStream  以及 FileOutputStream
對於Out以及Err又根據encoding 轉換爲PrintStream
然後通過本地方法進行設置
所以說,那三個專門的文件描述符一般不直接使用
取而代之的則是使用文件描述符 初始化設置過的流對象
 
image_5b923c63_5566
 
 
應用程序不創建文件描述符, 都是由系統調用, 也就是本地方法來操作的
應用程序只是獲得,  然後使用,  所謂使用,最終也還是需要藉助於操作系統
是應用程序 操作文件 時 與操作系統進行交互時,必須的數據項 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章