1. 程式人生 > >【雜談】Java I/O的底層實現

【雜談】Java I/O的底層實現

硬盤 字節數 lower jni 處理 裝飾器模式 eight dma 字節數組

前言

  Java I/O功能封裝的很好,使用起來很方便,就是剛開始學的時候,如果不了解裝飾器模式,會被他繁多的類給嚇到。用多了也就習慣了,而且現在有很多實用的封裝良好的實用類,可直接讀寫整個文件。開發者不知道底層實現細節,也可以靈活使用,這是封裝的一大優點。但是,作為一名軟件開發人員,對其所使用的代碼不能僅僅停留在熟悉功能特性上,最好對其實現原理也要有一定了解。

註:本文引用了部分外文內容,並根據自己的理解進行了翻譯,連接將在文末貼出。

--------------------------------------外文引用內容Begin(已翻譯)----------------------------------------------------------------

緩沖處理、內核空間vs用戶空間

  緩沖,以及如何處理緩沖是所有IO的基本內容。術語"I/O"(輸入輸出)指的不過就是從緩沖區移入或移除數據。通常,進程執行I/O操作的方式是,向操作系統發送請求,請求其填充自己的緩沖區(或者把自己緩沖區的內容寫出)。這就是I/O這個概念的全部內容。要實現這些傳輸操作,操作系統底層的實現非常復雜。但是在概念上,本文所要講述的內容則非常直白。

  技術分享圖片

  註意:User space和Kernel space 都屬於內存。內存分為兩個區,用戶區和系統區(內核區)。

  上圖簡要展示了,塊數據如何從外部源頭(比如硬盤)移入到進程的內存空間的過程。首先,這個進程通過系統調用read(),請求填充自己的緩沖區。這將導致內核發送一個命令到磁盤控制器,使其從磁盤中抓取數據。磁盤控制器通過DMA把數據直接寫入到內核空間緩沖區,這個過程不需要CPU幹預。一旦磁盤控制器完成了填充數據的任務,內核就將數據從內核空間的臨時緩沖區轉移到進程指定的緩沖區內。

  有一件事需要註意,內核會試圖緩沖或者說預加載一些數據,所以有可能進程所請求的數據已經在內核空間裏了。如果這樣的話,進程請求的數據,只需要從內核緩沖區拷貝一份即可。如果數據不在內核空間內,則在內核獲取數據到內存的過程中,此進程將被掛起。

--------------------------------------外文引用內容End(已翻譯)-------------------------------------------------------------------

從上述內容可知:

  • Java的讀寫操作,底層由C/C++實現。而不是直接與OS接觸
  • C/C++讀寫操作,需要OS服務
  • 內核自帶緩沖,會過分加載
  • 如果內存中沒有數據的緩沖,讀寫操作將阻塞當前線程(OS會幫你掛起線程)

DMA

  DMA(Direct Memory Access,直接內存存取)是I/O設備控制方式的一種。我個人認為它們的主要差別在於CPU的參與I/O控制的程度

I/O設備控制方式有:

  • 程序I/O方式——CPU需反復檢查
  • 中斷I/O方式——每完成一個字節的讀寫,通知CPU
  • DMA方式——每完成一個塊(多字節)的讀寫,通知CPU
  • I/O通道方式(暫不了解)

在DMA讀寫I/O設備的時候,CPU不會被影響,它可以繼續執行。註意!這裏能繼續執行,指的是CPU可以繼續運行,而此I/O操作的線程已經被掛起,不參與CPU調度。I/O操作完成後,該線程才被喚醒,參與調度(加入就緒隊列,等待時間片)

系統調用

  系統調用是應用程序間接調用OS函數的方式。C語言有提供與系統調用相對應的庫函數。這裏就是read、write。 

BufferedXXStream

  註意,對於Java來說,系統調用的開銷是比較大的。首先讀寫操作要觸發的是本地方法read0,readBytes,write0,writeBytes,這裏JNI需要一定開銷。還有就是每產生一個系統調用,就可能產生上千個機器指令,這種開銷是不容小覷的。所以,我們要嘗試減少系統調用。那有人就會問了,不行啊,我數據又不能缺斤少兩,少讀少寫肯定出問題,怎麽減少調用?這不是很好解決嗎,每次多讀寫一點,調用的次數不就少了嘛。而BufferedXXStream就是這麽用的,例如,BufferedInputStream的read無參方法只讀取一個字節,而實際上BufferedInputStream默認讀取了8kb,這些數據用字節數組保留。

  對了,如果對上圖,不是很理解,可以看看這張。

   即運行時,有一個對象BufferedInputStream,其調用一次read()方法,數據保留到buf數組中。

技術分享圖片

參考文獻  

How Java I/O Works Internally at Lower Level?(需FQ)

【雜談】Java I/O的底層實現