本發(fā)明隸屬于系統(tǒng)文件輸入輸出的技術(shù)領(lǐng)域,具體涉及一種基于JVM的磁盤直接I/O訪問的方法。
背景技術(shù):
一般的文件讀寫操作,都不可避免得使用到操作系統(tǒng)的文件系統(tǒng)的頁面高速緩存(Page Cache)。Page Cache具有幾個特點:首先,它是操作系統(tǒng)級別的全局內(nèi)存空間,在所有應(yīng)用程序間進(jìn)行空間共享。由于物理內(nèi)存有限,因此會出現(xiàn)資源爭用情況。其次,頁面高速緩存由操作系統(tǒng)統(tǒng)一管理,應(yīng)用程序不能直接控制和干涉Page Cache。這在實際工作中,會帶來如下問題:
第一、操作大文件時帶來的系統(tǒng)整體性能下降。當(dāng)讀寫大文件時,譬如當(dāng)執(zhí)行讀、寫、復(fù)制、移動、壓縮大文件的操作時,系統(tǒng)會消耗大量的Page Cache,由于物理內(nèi)存空間有限,導(dǎo)致系統(tǒng)中運(yùn)行中的其它應(yīng)用程序鎖使用的Page Cache空間被交換出去(swapped out),以釋放出足夠的Cache空間供其使用。這樣一來,其它程序I/O的響應(yīng)性能急劇下降,甚至?xí)霈F(xiàn)長時間無響應(yīng)的癥狀,直到文件操作完畢后,才會恢復(fù)正常響應(yīng)。這對于響應(yīng)性能要求高的服務(wù)器程序來說,是不可接受的。譬如在互聯(lián)網(wǎng)網(wǎng)站的服務(wù)端,由于大文件操作過程中該服務(wù)器無法在一定時間范圍內(nèi)完成響應(yīng),這意味著用戶瀏覽網(wǎng)站的響應(yīng)時間變長,甚至超時。
第二、數(shù)據(jù)一致性問題。Cache的維護(hù)成本高,應(yīng)用程序每次寫完文件后,實際上是更新了位于Cache中的文件,磁盤上的文件需要等到flush操作后才會刷到磁盤上。若flush之前系統(tǒng)宕機(jī),則會丟失這部分的數(shù)據(jù)更新。
第三、對底層硬件的控制力弱。傳統(tǒng)的基于JVM的應(yīng)用程序,都無法直接操縱硬件磁盤。雖然Page Cache能夠幫助程序提高I/O效率,但這對自緩存(Self-Caching)程序來說卻是個障礙。自緩存程序自身維護(hù)一套數(shù)據(jù)從硬件磁盤到內(nèi)存間的映射關(guān)系,它的緩存一致性維護(hù)機(jī)制往往是跟自身數(shù)據(jù)的邏輯結(jié)構(gòu)密切相關(guān),與傳統(tǒng)的操作系統(tǒng)Page Cache機(jī)制存在著較大差異。但是由于操作系統(tǒng)底層提供的Page Cache機(jī)制,橫亙在自緩存程序與底層磁盤硬件之間,造成昂貴的內(nèi)存資源的巨大浪費(fèi)。
JVM是Java Virtual Machine(Java虛擬機(jī))的縮寫,是一種用于計算設(shè)備的規(guī)范,它是一個虛構(gòu)出來的計算機(jī),是通過在實際的計算機(jī)上仿真模擬各種計算機(jī)功能來實現(xiàn)的。JVM為了保證程序的可移植性,對程序員屏蔽了底層硬件訪問細(xì)節(jié)。程序員只需要編寫Java語法的代碼,無須關(guān)心運(yùn)行平臺的處理器類型和操作系統(tǒng)。由JVM負(fù)責(zé)解釋Java程序,并轉(zhuǎn)換為能夠在特定處理器和操作系統(tǒng)上運(yùn)行的二進(jìn)制指令。所有的底層硬件訪問能力是由JVM提供的,并且JVM封裝了一部分接口,通過JDK暴露出API給Java程序員。對于上述磁盤直接IO訪問技術(shù),JDK并未提供支持。JDK是Java語言的軟件開發(fā)工具包,用于移動設(shè)備、嵌入式設(shè)備上的java應(yīng)用程序。JDK是整個java開發(fā)的核心,它包含了JAVA的運(yùn)行環(huán)境,JAVA工具和JAVA基礎(chǔ)的類庫。
技術(shù)實現(xiàn)要素:
為解決現(xiàn)有技術(shù)存在的局限性和不足,本發(fā)明的目的是通過利用JVM功能特性,通過配置提供文件操作函數(shù)的API層、屏蔽操作系統(tǒng)文件系統(tǒng)訪問差異的適配層、支持多種類編程語言轉(zhuǎn)換的語言轉(zhuǎn)換層、執(zhí)行訪問磁盤操作的直接調(diào)用I/O層,實現(xiàn)支持任何一種操作語言能跨越操作系統(tǒng)的頁面高速緩存,獲得直接操縱磁盤文件的能力,從根本上解決因系統(tǒng)宕機(jī)而導(dǎo)致的數(shù)據(jù)丟失問題,也有助于減少對系統(tǒng)全局資源的消耗,利于解決因操作大文件而引發(fā)其他程序I/O性能降低的難題。
技術(shù)方案如下:一種基于JVM的磁盤直接I/O訪問方法,通過利用JVM功能特性,配置提供文件操作函數(shù)的API層、屏蔽操作系統(tǒng)文件系統(tǒng)訪問差異的適配層、支持多種類編程語言轉(zhuǎn)換的語言轉(zhuǎn)換層、執(zhí)行訪問磁盤操作的直接調(diào)用I/O層,實現(xiàn)支持任何一種操作語言能跨越操作系統(tǒng)的頁面高速緩存,獲得直接操縱磁盤文件的能力;
在物理磁盤之上,基于系統(tǒng)架構(gòu)層原始的結(jié)構(gòu),包括API層、適配層、語言轉(zhuǎn)換層和直接調(diào)用I/O層,在相應(yīng)的層結(jié)構(gòu)上構(gòu)建文件操作接口函數(shù)、文件操作指令語言轉(zhuǎn)換接口函數(shù)、及直接訪問磁盤接口函數(shù);
層結(jié)構(gòu)部署完畢后,寫入數(shù)據(jù)請求,并根據(jù)請求內(nèi)容直接訪問磁盤,步驟包括:
步驟1:調(diào)用API層的文件打開函數(shù),傳入文件操作指令中的文件路徑名等參數(shù),返回文件句柄fd;所述文件句柄是指操作系統(tǒng)為每一個文件分配的唯一標(biāo)識,文件操作指令能通過文件句柄操作文件;在創(chuàng)建文件操作時,通過設(shè)置操作系統(tǒng)使用文件直接I/O訪問的屬性,使操作系統(tǒng)具備文件直接I/O訪問能力;
步驟2:調(diào)用API層的文件讀取函數(shù)或文件寫入函數(shù),提供傳入文件句柄fd、文件偏移量offset、長度len、內(nèi)存緩沖區(qū)buffer的參數(shù);
所述文件偏移量offset是指操作文件中數(shù)據(jù)的起始位置;
所述長度len是指操作文件中數(shù)據(jù)的字節(jié)數(shù);
所述內(nèi)存緩沖區(qū)buffer:文件讀取時,是指用來存放讀取數(shù)據(jù)的內(nèi)存區(qū)域;文件寫入時,是指用來存放待寫入數(shù)據(jù)的內(nèi)存區(qū)域;
步驟3:適配層讀取當(dāng)前運(yùn)行的操作系統(tǒng)的配置信息,并根據(jù)配置信息判斷該操作系統(tǒng)的類型,進(jìn)而通過利用JVM的功能特性,調(diào)用預(yù)存在語言轉(zhuǎn)換層中與操作系統(tǒng)對應(yīng)的語言轉(zhuǎn)換函數(shù),將文件操作函數(shù)轉(zhuǎn)換為當(dāng)前操作系統(tǒng)能識別的語言,使文件操作指令能在當(dāng)前操作系統(tǒng)內(nèi)執(zhí)行;
特別地,若不能根據(jù)當(dāng)前運(yùn)行的操作系統(tǒng),找到相匹配的語言轉(zhuǎn)換函數(shù),則提示“不支持本操作系統(tǒng)”的錯誤標(biāo)識;
步驟4:經(jīng)語言轉(zhuǎn)換層后的文件操作指令直接對磁盤進(jìn)行操作:通過提前在磁盤區(qū)內(nèi)設(shè)置文件操作指令對應(yīng)的文件指針,并根據(jù)文件偏移量offset,將文件指針移動至距離文件開始位置為文件偏移量offset的地方;同時,提前在內(nèi)存緩沖區(qū)中設(shè)置文件指針,并根據(jù)文件偏移量offset,將文件指針移動至距離文件開始位置為文件偏移量offset的地方;
步驟5:根據(jù)文件操作指令的內(nèi)容,判定文件是讀操作還是寫操作,并按照文件內(nèi)容所占字節(jié)數(shù)讀取或?qū)懭胂鄳?yīng)數(shù)據(jù)量的數(shù)據(jù);
若文件操作是讀操作,則從磁盤區(qū)內(nèi)文件指針當(dāng)前位置開始,讀取字節(jié)數(shù)為len的磁盤數(shù)據(jù),傳至內(nèi)存緩存區(qū)中;
若文件操作是寫操作,則從內(nèi)存緩沖區(qū)內(nèi)文件指針當(dāng)前位置開始,讀取字節(jié)數(shù)為len的緩沖數(shù)據(jù),傳至硬盤區(qū)中;
步驟6:文件讀操作或?qū)懖僮鹘Y(jié)束后,調(diào)用API層的關(guān)閉文件接口函數(shù),傳入文件句柄fd,關(guān)閉文件。
進(jìn)一步的,所述API層中構(gòu)建文件操作指令應(yīng)用于磁盤直接訪問的打開文件接口函數(shù)、關(guān)閉文件接口函數(shù)、讀取文件接口函數(shù)、寫入文件接口函數(shù),提供負(fù)責(zé)文件的打開、文件的關(guān)閉、文件的讀和寫;接口函數(shù)基于JVM語言編寫;
所述適配層根據(jù)當(dāng)前運(yùn)行的操作系統(tǒng),利用JVM的功能特性,選擇適合當(dāng)前操作系統(tǒng)的語言轉(zhuǎn)換接口函數(shù),使文件操作指令適應(yīng)于當(dāng)前操作系統(tǒng),屏蔽因不同操作系統(tǒng)需要不同操作語言的差異性;
所述語言轉(zhuǎn)換層按照轉(zhuǎn)換后的文件操作語言,提供實現(xiàn)適應(yīng)于當(dāng)前操作系統(tǒng)的文件操作函數(shù),用于之后執(zhí)行具體的磁盤文件直接讀寫操作;
所述直接調(diào)用I/O層按照當(dāng)前運(yùn)行的操作系統(tǒng),提供該操作系統(tǒng)的系統(tǒng)調(diào)用,直接訪問磁盤。
進(jìn)一步的,所述API層、適配層、語言轉(zhuǎn)換層及直接調(diào)用I/O層,每一個層結(jié)構(gòu)也能是具有相似功能的功能模塊。
進(jìn)一步的,步驟2中所述文件偏移量offset是指文件操作指令操作文件中數(shù)據(jù)的起始位置;所述長度len是指文件操作指令的操作文件中數(shù)據(jù)的字節(jié)數(shù);所述內(nèi)存緩沖區(qū)buffer:文件讀取時,是指用來存放讀取數(shù)據(jù)的內(nèi)存區(qū)域;文件寫入時,是指用來存放待寫入數(shù)據(jù)的內(nèi)存區(qū)域。
進(jìn)一步的,在步驟3中,若不能根據(jù)所述當(dāng)前運(yùn)行的操作系統(tǒng),找到相匹配的語言轉(zhuǎn)換函數(shù),則提示“不支持本操作系統(tǒng)”的錯誤標(biāo)識。
進(jìn)一步的,步驟5中,針對所述內(nèi)存緩沖區(qū)的內(nèi)存地址,應(yīng)按照操作系統(tǒng)內(nèi)存分頁大小,調(diào)整為內(nèi)存分頁大小的整數(shù)倍,以保持內(nèi)存緩沖區(qū)與內(nèi)存分頁的對齊。
在步驟5中,針對所述磁盤區(qū)讀寫的字節(jié)數(shù),應(yīng)按照磁盤扇區(qū)大小,調(diào)整為磁盤扇區(qū)大小的整數(shù)倍,以保持內(nèi)存緩沖區(qū)與扇區(qū)的對齊。
與現(xiàn)有技術(shù)相比,有益效果:
(1)本發(fā)明利用JVM功能特性,通過配置提供文件操作函數(shù)的API層、屏蔽操作系統(tǒng)文件系統(tǒng)訪問差異的適配層、支持多種類編程語言轉(zhuǎn)換的語言轉(zhuǎn)換層、執(zhí)行訪問磁盤操作的直接調(diào)用I/O層,支持任何一種操作語言能跨越操作系統(tǒng)的頁面高速緩存,獲得直接操縱磁盤文件的能力,減少對系統(tǒng)全局資源的消耗,有利于解決因操作大文件而引發(fā)其他程序I/O性能降低的難題;
(2)本發(fā)明中通過直接對磁盤執(zhí)行寫操作,使數(shù)據(jù)更新不再借助操作系統(tǒng)的頁面高速緩存,而是直接持久化入磁盤,從根本上解決因系統(tǒng)宕機(jī)而導(dǎo)致的數(shù)據(jù)丟失問題;
(3)本發(fā)明通過配置好的適配層和語言轉(zhuǎn)換層,使包含java在內(nèi)的基于JVM的編程語言經(jīng)轉(zhuǎn)換后,均能適用于支持訪問操作系統(tǒng)的系統(tǒng)調(diào)用,解決因不同操作系統(tǒng)需要不同編程語言而導(dǎo)致重復(fù)編程工作;
(4)本發(fā)明通過基于系統(tǒng)架構(gòu)層的原始結(jié)構(gòu),綜合利用JVM功能特性,使構(gòu)建的文件操作函數(shù)能以統(tǒng)一形式的API接口暴露給操作系統(tǒng),并適應(yīng)于在不同操作系統(tǒng)內(nèi)執(zhí)行磁盤直接I/O訪問,實現(xiàn)在各操作系統(tǒng)間的可移植,減少因操作系統(tǒng)差異而導(dǎo)致的人工修改;
附圖說明
圖1為本發(fā)明實施例中基于JVM的磁盤直接I/O訪問方法實施結(jié)構(gòu)圖
圖2為本發(fā)明實施例中基于JVM的磁盤直接I/O訪問方法實現(xiàn)流程圖
圖3為本發(fā)明實施例中對磁盤直接讀寫的流程示意圖
具體實施方式
為使本發(fā)明的目的、技術(shù)方案和優(yōu)點更加清楚明白,下面對本發(fā)明實施例中一種基于JVM的磁盤直接I/O訪問方法中所涉及的一些術(shù)語做簡單解釋:
所述文件句柄fd是指操作系統(tǒng)為每一個文件分配的唯一標(biāo)識,文件操作指令能通過文件句柄操作文件;
所述文件偏移量offset是指操作文件中數(shù)據(jù)的起始位置;
所述長度len是指操作文件中數(shù)據(jù)的字節(jié)數(shù);
所述內(nèi)存緩沖區(qū)buffer:文件讀取時,是指用來存放讀取數(shù)據(jù)的內(nèi)存區(qū)域;文件寫入時,是指用來存放待寫入數(shù)據(jù)的內(nèi)存區(qū)域。
為了使本發(fā)明的目的、技術(shù)方案和優(yōu)點更加清楚,下面結(jié)合附圖和具體實施例對本發(fā)明進(jìn)行詳細(xì)描述。
基于系統(tǒng)架構(gòu)層原始的結(jié)構(gòu),包括API層、適配層、語言轉(zhuǎn)換層和直接調(diào)用I/O層,配置本發(fā)明需要的層結(jié)構(gòu),包括:
(1)API層中構(gòu)建應(yīng)用于磁盤直接訪問的打開文件接口函數(shù)、關(guān)閉文件接口函數(shù)、讀取文件接口函數(shù)、寫入文件接口函數(shù),提供負(fù)責(zé)文件的打開、文件的關(guān)閉、文件的讀和寫;接口函數(shù)基于JVM語言編寫;
(2)適配層負(fù)責(zé)根據(jù)當(dāng)前運(yùn)行的操作系統(tǒng),利用JVM的功能特性,選擇適合當(dāng)前操作系統(tǒng)的語言轉(zhuǎn)換接口函數(shù),使文件操作指令適應(yīng)于當(dāng)前操作系統(tǒng),屏蔽因不同操作系統(tǒng)需要不同操作語言的差異性;
(3)語言轉(zhuǎn)換層按照轉(zhuǎn)換后的文件操作語言,提供實現(xiàn)適應(yīng)于當(dāng)前操作系統(tǒng)的文件操作函數(shù),用于之后執(zhí)行具體的磁盤文件直接讀寫操作;
(4)直接調(diào)用I/O層按照當(dāng)前運(yùn)行的操作系統(tǒng),提供該操作系統(tǒng)的系統(tǒng)調(diào)用,直接訪問磁盤;
圖1為本發(fā)明實施例中基于JVM的磁盤直接I/O訪問方法實施結(jié)構(gòu)圖中,
在物理磁盤之上,基于系統(tǒng)架構(gòu)層原始的結(jié)構(gòu),包括API層101、適配層102、語言轉(zhuǎn)換層103和直接調(diào)用I/O層104,配置本發(fā)明需要的層結(jié)構(gòu),包括:
所述API層101中以基于JVM的編程語言構(gòu)建打開文件接口函數(shù)open、關(guān)閉文件接口函數(shù)close、讀取文件接口函數(shù)read、寫入文件接口函數(shù)write,提供負(fù)責(zé)文件的打開、文件的關(guān)閉、文件的讀和寫;
其中,所述基于JVM的編程語言包括Java、Scala、Groovy、Clojure等;
API層101內(nèi)所有文件操作功能函數(shù)接口按照如下全限定名方式定義:
(1)Java_java_dio_DFile_open函數(shù):文件打開接口;
(2)Java_java_dio_DFile_close函數(shù):文件關(guān)閉接口;
(3)Java_java_dio_DFile_read函數(shù):文件讀接口;
(4)Java_java_dio_DFile_write函數(shù):文件寫接口;
所述適配層102負(fù)責(zé)根據(jù)當(dāng)前運(yùn)行的操作系統(tǒng),選取適合當(dāng)前操作系統(tǒng)的語言轉(zhuǎn)換層函數(shù),使文件操作指令能適應(yīng)于當(dāng)前操作系統(tǒng),屏蔽因不同操作系統(tǒng)需要不同操作語言的差異性;
所述語言轉(zhuǎn)換層103提供基于JVM編程語言的適應(yīng)于不同操作系統(tǒng)的語言轉(zhuǎn)換接口函數(shù);當(dāng)文件操作指令轉(zhuǎn)換成能適應(yīng)于操作系統(tǒng)內(nèi)執(zhí)行的語言時,語言轉(zhuǎn)換層按照轉(zhuǎn)換后的文件操作語言,提供文件操作的接口函數(shù),實現(xiàn)具體的文件操作;
如下是經(jīng)轉(zhuǎn)換后適應(yīng)于Linux系統(tǒng)的文件操作函數(shù):
(1)Java_java_dio_DFile_imp_{Linux}_open函數(shù):文件打開函數(shù);
(2)Java_java_dio_DFile_imp_{Linux}_close函數(shù):文件關(guān)閉函數(shù);
(3)Java_java_dio_DFile_imp_{Linux}_read函數(shù):文件讀函數(shù);
(4)Java_java_dio_DFile_imp_{Linux}_write函數(shù):文件寫函數(shù);
所述直接調(diào)用I/O層104按照當(dāng)前運(yùn)行的操作系統(tǒng),提供該操作系統(tǒng)的系統(tǒng)調(diào)用功能,直接訪問磁盤;
本發(fā)明實施例中的操作系統(tǒng)是Linux系統(tǒng),經(jīng)層結(jié)構(gòu)部署完畢后,寫入數(shù)據(jù)請求,并根據(jù)請求內(nèi)容直接訪問磁盤,圖2為本發(fā)明實施例中基于JVM的磁盤直接I/O訪問方法實現(xiàn)流程圖,具體包括:
步驟201:調(diào)用API層101的文件打開函數(shù),傳入文件路徑名等參數(shù),返回文件句柄fd,獲取操作文件的標(biāo)識;
步驟202:設(shè)置Linux系統(tǒng)的文件直接I/O訪問屬性,啟動Linux文件直接I/O訪問能力;
步驟203:根據(jù)讀取文件或?qū)懭胛募男枰?,調(diào)用API層101中文件讀取函數(shù)或文件寫入函數(shù),提供傳入文件句柄fd、文件偏移量offset、長度len、內(nèi)存緩沖區(qū)buffer的參數(shù);
步驟204:適配層102讀取當(dāng)前運(yùn)行的操作系統(tǒng)的配置信息,并根據(jù)配置信息判斷該操作系統(tǒng)的類型,進(jìn)而利用JNI調(diào)用預(yù)存在語言轉(zhuǎn)換層中與操作系統(tǒng)對應(yīng)的語言轉(zhuǎn)換函數(shù),將基于JVM語言編寫的文件操作函數(shù)轉(zhuǎn)換為當(dāng)前操作系統(tǒng)能識別的語言,使文件操作指令能在當(dāng)前操作系統(tǒng)內(nèi)執(zhí)行;
步驟205:開辟內(nèi)存緩沖區(qū),語言轉(zhuǎn)換層103利用經(jīng)語言轉(zhuǎn)換后的文件操作指令直接對磁盤執(zhí)行讀操作或?qū)懖僮?,如圖3所示,具體包括:
步驟205-1:獲取操作系統(tǒng)的內(nèi)存分頁大小,并調(diào)整開辟的內(nèi)存緩存區(qū)的內(nèi)存地址為內(nèi)存分頁大小的整數(shù)倍,保證內(nèi)存緩沖區(qū)與系統(tǒng)內(nèi)存的對齊;
步驟205-2:獲取物理磁盤扇葉大小,調(diào)整每次讀、寫的字節(jié)數(shù)為物理磁盤扇葉大小的整數(shù)倍,保證讀取文件數(shù)量與物理磁盤扇區(qū)的對齊;
步驟205-3:在物理磁盤區(qū)和內(nèi)存緩存區(qū)分別設(shè)置文件指針,根據(jù)文件偏移量offset,在磁盤區(qū)中將文件指針移動至距離文件開始位置為文件偏移量offset的地方,在內(nèi)存緩存區(qū)中將文件指針移動至距離文件開始位置為文件偏移量offset的地方;
步驟205-4:若文件操作是讀操作,則從磁盤區(qū)內(nèi)文件指針當(dāng)前位置開始,讀取字節(jié)數(shù)為len的磁盤數(shù)據(jù),傳至內(nèi)存緩存區(qū)中;
步驟205-5:若文件操作是寫操作,則從內(nèi)存緩沖區(qū)內(nèi)文件指針當(dāng)前位置開始,讀取字節(jié)數(shù)為len的緩沖數(shù)據(jù),傳至硬盤區(qū)中;
步驟206:文件讀操作或?qū)懖僮鹘Y(jié)束后,調(diào)用API層的關(guān)閉文件接口函數(shù),傳入文件句柄fd,關(guān)閉文件;
所屬領(lǐng)域的普通技術(shù)人員應(yīng)當(dāng)理解:以上所述僅為本發(fā)明的具體實施例而已,并不用于限制本發(fā)明,凡在本發(fā)明的精神和原則之內(nèi),所做的任何修改、等同替換、改進(jìn)等,均應(yīng)包含在本發(fā)明的保護(hù)范圍之內(nèi)。