專利名稱:一種基于進(jìn)程間繼承關(guān)系的爪哇程序進(jìn)程守護(hù)方法
技術(shù)領(lǐng)域:
本發(fā)明是一種在windows系統(tǒng)(一種操作系統(tǒng)的名稱)中,針對(duì)爪哇程序(使用爪 哇編程語言開發(fā)的程序,以下稱java程序)進(jìn)行守護(hù)的方法。主要用來解決被守護(hù)的java 程序進(jìn)程的鑒別和確定,并對(duì)該java程序的運(yùn)行狀態(tài)進(jìn)行監(jiān)控,防止其意外終止運(yùn)行,屬 于計(jì)算軟件安全技術(shù)領(lǐng)域。
背景技術(shù):
在windows下運(yùn)行的一個(gè)應(yīng)用程序可能會(huì)異常退出,這種退出并非程序當(dāng)初設(shè)計(jì) 時(shí)的意愿,引起這種異常退出可能是程序自身內(nèi)部的錯(cuò)誤,或者是被其他程序強(qiáng)行終止,也 可能是非法用戶執(zhí)行退出操作。這些情況下,程序往往需要被重新啟動(dòng)才能實(shí)現(xiàn)其功能或 向外提供服務(wù)。對(duì)于無人值守的服務(wù)器或者是后臺(tái)運(yùn)行的服務(wù)程序,用戶并不能及時(shí)重新 啟動(dòng)他們;對(duì)于計(jì)算機(jī)系統(tǒng)中的殺毒軟件或者防火墻等安全產(chǎn)品而言,如果有程序或用戶 惡意結(jié)束它們,將會(huì)對(duì)系統(tǒng)安全造成一定的損失甚至嚴(yán)重后果。此時(shí)就需要一種機(jī)制能夠 實(shí)施實(shí)時(shí)監(jiān)控,一旦檢測(cè)到被守護(hù)的程序退出,就立即啟動(dòng)它,這就是進(jìn)程守護(hù)技術(shù)。但是 作為一種安全輔助手段,這種檢測(cè)機(jī)制不能對(duì)系統(tǒng)本身的性能產(chǎn)生明顯的影響,否則就會(huì) 影響保護(hù)的被守護(hù)程序的服務(wù)效果,失去輔助程序的意義。一般地,windows下正在運(yùn)行的一個(gè)應(yīng)用程序?qū)?yīng)著一個(gè)進(jìn)程,該進(jìn)程由兩部分構(gòu) 成操作系統(tǒng)用于管理目的的進(jìn)程內(nèi)核對(duì)象和該進(jìn)程所擁有的一個(gè)地址空間。其中內(nèi)核對(duì) 象是windows系統(tǒng)中最重要的概念之一,進(jìn)程的內(nèi)核對(duì)象只是所有內(nèi)核對(duì)象中的一種。內(nèi) 核對(duì)象的用途非常廣泛,其中之一便是可以用來進(jìn)行同步。這些內(nèi)核對(duì)象中的每一種要么 處于觸發(fā)狀態(tài),要么處于未觸發(fā)狀態(tài)。關(guān)于進(jìn)程內(nèi)核對(duì)象,微軟公司為其指定了一些規(guī)則, 規(guī)定如何在這兩種狀態(tài)之間進(jìn)行轉(zhuǎn)換。進(jìn)程內(nèi)核對(duì)象在進(jìn)程創(chuàng)建的時(shí)候總是處于未觸發(fā)狀 態(tài),當(dāng)進(jìn)程終止的時(shí)候,操作系統(tǒng)就會(huì)自動(dòng)使進(jìn)程內(nèi)核對(duì)象變成觸發(fā)狀態(tài),并且當(dāng)進(jìn)程內(nèi)核 對(duì)象被觸發(fā)以后,它將永遠(yuǎn)保持這種狀態(tài),再也回不到未觸發(fā)狀態(tài)。在進(jìn)程內(nèi)核對(duì)象的內(nèi) 部有一個(gè)布爾變量,當(dāng)系統(tǒng)創(chuàng)建進(jìn)程時(shí),將此進(jìn)程內(nèi)核對(duì)象的布爾變量初始化為FALSE(表 示未觸發(fā));當(dāng)進(jìn)程終止的時(shí)候,操作系統(tǒng)又會(huì)將這個(gè)布爾變量設(shè)為TRUE(表示已經(jīng)被觸 發(fā))。基于此,可以編寫程序來測(cè)試一個(gè)進(jìn)程內(nèi)核對(duì)象的狀態(tài),以確定該進(jìn)程是否正在運(yùn)行。 windows已經(jīng)提供了相關(guān)的API (應(yīng)用程序編程接口 )用于檢查進(jìn)程內(nèi)核對(duì)象的布爾值,而 且將調(diào)用該線程設(shè)置為等待狀態(tài),直到被守護(hù)的進(jìn)程內(nèi)核對(duì)象從FALSE變?yōu)門RUE的時(shí)候自 動(dòng)喚醒等待的線程繼續(xù)運(yùn)行。java語言(爪哇編程語言)是目前最流行的編程語言之一,其特點(diǎn)之一便是編譯 一次到處運(yùn)行,現(xiàn)在已經(jīng)成為許多應(yīng)用方便的首選編程語言。在windows下,一個(gè)應(yīng)用程序 的磁盤文件一般即為一個(gè)可直接運(yùn)行的exe文件(一種可執(zhí)行文件的稱呼)。但由于生成 exe文件總要和系統(tǒng)的硬件平臺(tái)相關(guān),這和java的跨平臺(tái)性是相悖的,所以java語言并不 支持直接產(chǎn)生一個(gè)可執(zhí)行的exe文件。一個(gè)GUI (圖形化用戶接口)應(yīng)用程序,在開發(fā)過程 中,可以使用java class文件(開發(fā)過程中的一種文件形式)來運(yùn)行程序,但是最后發(fā)布應(yīng)用程序的時(shí)候一般需將若干個(gè)class文件打包成一種jar文件(java檔案文件),而不直 接產(chǎn)生如windows下的exe文件,這些jar文件可以像exe那樣雙擊運(yùn)行。jar文件本身只 是java文檔的一種文檔格式。在windows下安裝JRE(Java運(yùn)行環(huán)境)的時(shí)候,系統(tǒng)已經(jīng) 將該文件類型關(guān)聯(lián)到j(luò)avaw. exe (運(yùn)行java程序時(shí)具體的執(zhí)行文件)程序上,即雙擊該文 件時(shí)實(shí)際是啟動(dòng)一個(gè)javaw. exe來打開jar文件并運(yùn)行程序功能,在操作系統(tǒng)中具體表現(xiàn) 為一個(gè)叫javaw. exe的進(jìn)程。因此如果系統(tǒng)中有多個(gè)打包為jar的⑶I應(yīng)用程序同時(shí)在運(yùn) 行,也就運(yùn)行了多個(gè)javaw. exe的進(jìn)程,從任務(wù)管理器中會(huì)看到多個(gè)名字都為javaw. exe的 進(jìn)程實(shí)例在運(yùn)行。傳統(tǒng)進(jìn)程守護(hù)方法分析現(xiàn)有的進(jìn)程守護(hù)方法如圖1。該方法在運(yùn)行過程中每隔一定時(shí)間查詢系統(tǒng)當(dāng)前運(yùn) 行的進(jìn)程實(shí)例,具體操作是對(duì)當(dāng)前系統(tǒng)拍快照,對(duì)所得的數(shù)據(jù)結(jié)構(gòu),通過匹配被守護(hù)進(jìn)程的 名字從而確定系統(tǒng)中是否有被守護(hù)進(jìn)程正在運(yùn)行。這種方法要求不停的查詢系統(tǒng),這將會(huì) 消耗大量的系統(tǒng)資源。雖然將查詢頻率設(shè)定為一定的間隔可以減少查詢次數(shù)從而降低對(duì)系 統(tǒng)資源的占用。但是在對(duì)java應(yīng)用程序進(jìn)行守護(hù)的時(shí)候,是無法通過匹配被守護(hù)進(jìn)程名字 來確定被守護(hù)進(jìn)程是否存在的。因?yàn)楫?dāng)系統(tǒng)中有多個(gè)Java程序在同時(shí)運(yùn)行時(shí),可能會(huì)出現(xiàn) 多個(gè)javaw. exe的進(jìn)程。這些進(jìn)程對(duì)應(yīng)著系統(tǒng)中同一個(gè)javaw. exe文件,它是打開jar格 式文件實(shí)現(xiàn)應(yīng)用程序功能的實(shí)體,通過這種簡(jiǎn)單的查詢法方法并不能確定哪個(gè)javaw. exe 對(duì)應(yīng)被守護(hù)程序,也就不能確定被守護(hù)應(yīng)用程序是否正在運(yùn)行。因此傳統(tǒng)的進(jìn)程守護(hù)方法 在這種情況下失效了。還有一種方法是由需要被守護(hù)的程序自身來創(chuàng)建遠(yuǎn)程線程,病毒木馬常使用這種 方法,具體是在應(yīng)用程序自身啟動(dòng)時(shí),準(zhǔn)備好遠(yuǎn)程線程所需的代碼和數(shù)據(jù),然后通過在其他 進(jìn)程中分配內(nèi)存空間并將這些代碼和數(shù)據(jù)寫到遠(yuǎn)程進(jìn)程中,然后啟動(dòng)遠(yuǎn)程線程,由該遠(yuǎn)程 線程執(zhí)行進(jìn)程守護(hù)的功能。這種方法在windows下現(xiàn)在容易被殺毒軟件誤報(bào)為病毒或者被 主動(dòng)防御攔截,從而影響用戶的體驗(yàn)性,而且這種將代碼寫到其他進(jìn)程的方法會(huì)影響其他 進(jìn)程的穩(wěn)定性。所以這種方法應(yīng)該是一個(gè)正常應(yīng)用程序盡量避免的方法。另外這一套方案 一般是在windows平臺(tái)上是使用c/c++(編程開發(fā)語言)開發(fā)應(yīng)用程序時(shí)才有可能使用的。 如果被守護(hù)的應(yīng)用程序的是使用java編程語言寫的,那么這種方案顯然是不合適的。
發(fā)明內(nèi)容
技術(shù)問題本發(fā)明的目的是提供一種在windows環(huán)境下對(duì)被打包成jar格式的 java程序?qū)崿F(xiàn)進(jìn)程守護(hù)的方法。該方法不僅減少了資源消耗量,提高主程序的健壯性,而且 具有使用靈活,方便升級(jí)的特點(diǎn)。技術(shù)方案本發(fā)明是利用父進(jìn)程和子進(jìn)程之間的一一對(duì)應(yīng)關(guān)系,在原有進(jìn)程查詢 機(jī)制的基礎(chǔ)上獲得對(duì)應(yīng)于被守護(hù)的java程序的進(jìn)程信息,并借助被守護(hù)的java程序進(jìn)程 內(nèi)核對(duì)象的狀態(tài)來監(jiān)視該java程序的運(yùn)行狀態(tài)。父進(jìn)程和子進(jìn)程在設(shè)計(jì)應(yīng)用程序時(shí),有時(shí)需要啟動(dòng)多任務(wù)執(zhí)行其他操作,同時(shí)本身的操作還繼續(xù) 進(jìn)行。要這樣做可以創(chuàng)建另一個(gè)本地線程,在該線程中執(zhí)行其他操作,這就是多線程程序。 但在有的場(chǎng)合下這樣做并不合適,如需要進(jìn)程守護(hù)時(shí)。一個(gè)線程監(jiān)視它所處的進(jìn)程運(yùn)行狀態(tài)是不合適的,因?yàn)槿绻M(jìn)程意外終止了,那么進(jìn)程之中執(zhí)行守護(hù)的線程還沒有來得及反 應(yīng)就隨主進(jìn)程的終止而結(jié)束了,也就無法實(shí)現(xiàn)進(jìn)程守護(hù)的功能。另一方面,處在同一進(jìn)程中 的多個(gè)線程訪問的是同一個(gè)進(jìn)程地址空間,如果其中一個(gè)線程不經(jīng)意地修改了重要內(nèi)容會(huì) 導(dǎo)致一些意想不到的結(jié)果。同時(shí)進(jìn)程守護(hù)的功能跟應(yīng)用程序的主體功能關(guān)聯(lián)性并不大,所 以可以將它獨(dú)立出去放到另一個(gè)單獨(dú)的進(jìn)程中去完成守護(hù)任務(wù),提高整體的健壯性。由于 主體應(yīng)用部分使用java語言開發(fā),為簡(jiǎn)化操作它只需簡(jiǎn)單的啟動(dòng)另一個(gè)可執(zhí)行文件,由該 進(jìn)程專門實(shí)現(xiàn)守護(hù)任務(wù),然后主體程序?qū)P膶?shí)現(xiàn)自己的任務(wù)。只要保證守護(hù)進(jìn)程的名字不 變,內(nèi)部實(shí)現(xiàn)則和主體部分沒有關(guān)系,這樣就可以使用windows系統(tǒng)下功能強(qiáng)大的各種API 來實(shí)現(xiàn)守護(hù)功能,不僅提高模塊化,而且使用起來更加靈活,也方便升級(jí)。標(biāo)識(shí)進(jìn)程在windows下一個(gè)進(jìn)程啟動(dòng)后,系統(tǒng)會(huì)給它分配一個(gè)標(biāo)識(shí)符即PID (進(jìn)程標(biāo)識(shí)符), PID是一個(gè)DWORD(—種數(shù)據(jù)類型名稱)類型的數(shù)據(jù),并且系統(tǒng)保證在該進(jìn)程運(yùn)行期間,這 個(gè)PID是和該進(jìn)程一一對(duì)應(yīng)的,即不會(huì)有其他進(jìn)程擁有一樣的PID,所以可以通過PID來 唯一標(biāo)識(shí)一個(gè)正在運(yùn)行的進(jìn)程。windows提供了 API函數(shù)接口來獲得當(dāng)前進(jìn)程的PIDJP GetCurrentProcessldO。同時(shí)windows還提供了另一套功能強(qiáng)大的函數(shù)庫I^oolhelpS〗 庫(windows操作系統(tǒng)提供的一組開發(fā)包)來幫助獲得當(dāng)前系統(tǒng)正在運(yùn)行的應(yīng)用程序的 信息,其工作機(jī)制是windows系統(tǒng)為所有當(dāng)前在系統(tǒng)內(nèi)存中的進(jìn)程、線程以及模塊等的 當(dāng)前狀態(tài)信息制作了一個(gè)只讀副本,即系統(tǒng)快照,系統(tǒng)用戶通過訪問該系統(tǒng)快照,進(jìn)行某 種類型信息的匹配就可以實(shí)現(xiàn)對(duì)被守護(hù)進(jìn)程的當(dāng)前狀態(tài)的檢測(cè)??煺諏?shí)際上是一個(gè)個(gè) PR0CESSENTRY32(—種數(shù)據(jù)結(jié)構(gòu)名稱)類型的數(shù)據(jù)結(jié)構(gòu),每個(gè)結(jié)構(gòu)對(duì)應(yīng)一個(gè)進(jìn)程,包含了 該進(jìn)程的各種信息,在這里使用th32ProcessID和th32ParentProcessID(數(shù)據(jù)結(jié)構(gòu)的名 稱)字段,這兩個(gè)字段之間即表示了兩個(gè)進(jìn)程之間的繼承關(guān)系。借助T00lHelp32庫中的各 種函數(shù)不僅可以獲取進(jìn)程快照,而且對(duì)于堆、模塊和線程的系統(tǒng)快照同樣可以獲取。這里 枚舉進(jìn)程只需用如下三個(gè) API 函數(shù)CreateToolhelp32Snapshot()、Process32First ()和 Process32Next()。第一步是用 Create^ToolhelpSZSnapshot ()函數(shù)創(chuàng)建系統(tǒng)信息“快照”。 這個(gè)函數(shù)可以讓你選擇存儲(chǔ)在快照中的信息類型。這里只是對(duì)進(jìn)程信息感興趣,因此只要 包含 TH32CS_SNAPPR0CESS (—種預(yù)先定義的宏)標(biāo)志即可。CreateToolhelp32Snapshot () 函數(shù)返回一個(gè)HANDLE (—種標(biāo)識(shí)符),完成調(diào)用之后,必須將此HANDLE傳給CloseHandle (), 關(guān)閉對(duì)該HANDLE的引用,這樣系統(tǒng)才能釋放相關(guān)資源。接下來調(diào)用ft~OCesS32FirSt()函 數(shù),從快照中獲取進(jìn)程信息,然后可以重復(fù)調(diào)用ft~OCesS32Next,直到函數(shù)返回FALSE為止, 這兩個(gè)函數(shù)都帶兩個(gè)參數(shù),它們分別是快照句柄和一個(gè)PR0CESSENTRY32結(jié)構(gòu)。調(diào)用這個(gè)兩 個(gè)函數(shù)就可以獲得一個(gè)進(jìn)程的信息,然后就可以匹配信息查看是否是被守護(hù)進(jìn)程。在這些 系統(tǒng)設(shè)施的基礎(chǔ)上,執(zhí)行一定的流程就可以確定被守護(hù)的java程序進(jìn)程的PID,也就確定 了對(duì)應(yīng)于被守護(hù)的爪哇程序的javaw. exe進(jìn)程,而不是面對(duì)多個(gè)不確定的javaw. exe進(jìn)程。獲取進(jìn)程內(nèi)核對(duì)象狀態(tài)對(duì)被守護(hù)的爪哇程序進(jìn)程的運(yùn)行狀態(tài)進(jìn)行監(jiān)視,可以通過監(jiān)視其進(jìn)程的內(nèi)核對(duì)象 狀態(tài)來實(shí)現(xiàn)。在windows中內(nèi)核對(duì)象是某種數(shù)據(jù)結(jié)構(gòu),只能由內(nèi)核訪問,所以應(yīng)用程序不能 直接訪問內(nèi)核對(duì)象,只能通過一系列的函數(shù)接口來操縱這些數(shù)據(jù)結(jié)構(gòu)。在32位的系統(tǒng)中, 系統(tǒng)使用一個(gè)32位的值即句柄來標(biāo)識(shí)一個(gè)對(duì)象。調(diào)用訪問或者創(chuàng)建內(nèi)核對(duì)象的函數(shù)后,函數(shù)會(huì)返回一個(gè)句柄,使用這個(gè)句柄即意味著對(duì)它所標(biāo)識(shí)的對(duì)象進(jìn)行某種操作。如果已經(jīng)知 道被守護(hù)進(jìn)程的PID,就可以借助windows API函數(shù)HANDLE OpenProcess ()獲得該進(jìn)程對(duì) 象的HANDLE,然后就可以使用這個(gè)HANDLE來訪問對(duì)應(yīng)的內(nèi)核對(duì)象獲知它的狀態(tài),要使用的 API 函數(shù)為 WaitForSingleObjectO。其函數(shù)原型為DW0RD WaitForSingleObject (HANDL EhHandle, DWORD dwMilliseconds),hHandle 為要監(jiān)視的內(nèi)核對(duì)象的句柄;dwMiIliseconds 為hHandle對(duì)象所設(shè)置的超時(shí)值,單位為毫秒。當(dāng)在某一線程中調(diào)用該函數(shù)時(shí),線程暫時(shí)掛 起,系統(tǒng)監(jiān)視hHandle所指向的對(duì)象的狀態(tài)。如果在掛起的dwMilliseconds毫秒內(nèi),線程 所等待的對(duì)象變觸發(fā)狀態(tài),則該函數(shù)立即返回;如果超時(shí)時(shí)間已經(jīng)到達(dá)dwMilliseconds毫 秒,但hHandle所指向的對(duì)象還沒有變成觸發(fā)狀態(tài),函數(shù)也返回。參數(shù)dwMilliseconds有 兩個(gè)具有特殊意義的值0和INFINITE ( 一個(gè)預(yù)定義的宏)。若為0,則該函數(shù)立即返回;若 為INFINITE,則線程一直被掛起,直到hHandle所指向的對(duì)象變?yōu)橛|發(fā)狀態(tài),這里是要一直 等待直到被守護(hù)進(jìn)程對(duì)象變?yōu)橛|發(fā)狀態(tài),所以設(shè)置為INFINITE。方法流程該方法在被守護(hù)的爪哇程序進(jìn)程與守護(hù)程序進(jìn)程之間建立一種父子繼承關(guān)系,并 基于這種繼承關(guān)系由守護(hù)程序進(jìn)程來唯一確定被守護(hù)的爪哇程序進(jìn)程;基于被守護(hù)的爪哇 程序進(jìn)程的內(nèi)核對(duì)象狀態(tài)確定被守護(hù)的爪哇程序的運(yùn)行狀態(tài);a.基于父子繼承關(guān)系確定被守護(hù)的爪哇程序進(jìn)程的方法為步驟al).被守護(hù)的爪哇程序進(jìn)程啟動(dòng)守護(hù)程序進(jìn)程,這樣被守護(hù)的爪哇程序進(jìn) 程為父進(jìn)程,守護(hù)程序進(jìn)程成為被守護(hù)的爪哇程序進(jìn)程的子進(jìn)程,在這兩個(gè)進(jìn)程之間建立 一種繼承關(guān)系,一個(gè)子進(jìn)程只有一個(gè)父進(jìn)程,由守護(hù)程序進(jìn)程來唯一確定被守護(hù)的爪哇程 序進(jìn)程;步驟a2).守護(hù)程序進(jìn)程獲得自身進(jìn)程標(biāo)識(shí)符PID,該P(yáng)ID在守護(hù)程序進(jìn)程運(yùn)行期 間唯一地標(biāo)識(shí)守護(hù)程序進(jìn)程,使用進(jìn)程名字標(biāo)識(shí)一個(gè)進(jìn)程并不準(zhǔn)確,系統(tǒng)中同時(shí)運(yùn)行多個(gè) 同名的進(jìn)程,要獲得守護(hù)程序進(jìn)程的PID使用系統(tǒng)應(yīng)用程序編程接口即可,這樣做有利于 提高程序的移植性;步驟a3).守護(hù)程序進(jìn)程對(duì)系統(tǒng)拍快照,快照是操作系統(tǒng)為所有當(dāng)前運(yùn)行的進(jìn)程、 線程的當(dāng)前信息狀態(tài)制作的一個(gè)只讀副本,具體表現(xiàn)為一組數(shù)據(jù)結(jié)構(gòu),其中的每個(gè)結(jié)構(gòu)又 包含各個(gè)成員數(shù)據(jù),這些成員含有進(jìn)程名字、進(jìn)程執(zhí)行路徑、進(jìn)程PID和父進(jìn)程PID信息,使 用windows操作系統(tǒng)提供的函數(shù)庫Toolhelp32獲取系統(tǒng)快照;步驟a4).守護(hù)程序進(jìn)程從系統(tǒng)快照中找到包含守護(hù)程序進(jìn)程信息的數(shù)據(jù)結(jié)構(gòu), 在上一步驟獲得的一組數(shù)據(jù)結(jié)構(gòu)中,守護(hù)進(jìn)程需要搜索其中的每個(gè)數(shù)據(jù)結(jié)構(gòu),將其中的PID 成員字段和守護(hù)程序進(jìn)程在步驟a2)中獲得的自身PID進(jìn)行匹配,一旦匹配即找到包含守 護(hù)程序進(jìn)程信息的數(shù)據(jù)結(jié)構(gòu);步驟a5).保存父進(jìn)程PID即被守護(hù)的爪哇程序進(jìn)程PID,在包含守護(hù)程序進(jìn)程信 息的數(shù)據(jù)結(jié)構(gòu)中有一個(gè)成員記錄著守護(hù)程序進(jìn)程的父進(jìn)程PID,這個(gè)PID唯一地標(biāo)識(shí)被守 護(hù)的爪哇程序進(jìn)程,這樣就不必?fù)?dān)心操作系統(tǒng)中同時(shí)有多個(gè)爪哇程序進(jìn)程在運(yùn)行,將該父 進(jìn)程PID值提取并保存起來;b.基于被守護(hù)的爪哇程序進(jìn)程的內(nèi)核對(duì)象狀態(tài)確定被守護(hù)的爪哇程序的運(yùn)行狀 態(tài)的方法為
6
步驟bl).守護(hù)程序進(jìn)程根據(jù)保存的父進(jìn)程PID通過系統(tǒng)的應(yīng)用程序編程接口打 開被守護(hù)的爪哇程序進(jìn)程,應(yīng)用程序編程接口會(huì)返回一個(gè)句柄,該句柄標(biāo)識(shí)被守護(hù)的爪哇 程序進(jìn)程的內(nèi)核對(duì)象,使用該句柄即意味著對(duì)被守護(hù)的爪哇程序進(jìn)程的操作;步驟1^2).守護(hù)程序進(jìn)程將步驟bl中返回的爪哇程序進(jìn)程內(nèi)核對(duì)象句柄傳給應(yīng)用 程序編程接口來訪問被守護(hù)的爪哇程序進(jìn)程,這時(shí)守護(hù)程序進(jìn)程進(jìn)入阻塞狀態(tài),直到被守 護(hù)的爪哇程序進(jìn)程內(nèi)核對(duì)象被觸發(fā)才繼續(xù)執(zhí)行;步驟b3).當(dāng)被守護(hù)的爪哇程序進(jìn)程不在運(yùn)行時(shí),操作系統(tǒng)觸發(fā)該進(jìn)程的內(nèi)核對(duì) 象,守護(hù)程序進(jìn)程繼續(xù)執(zhí)行,這時(shí)守護(hù)程序進(jìn)程重新啟動(dòng)被守護(hù)的爪哇程序;步驟b4).守護(hù)程序進(jìn)程自身退出運(yùn)行,至此它已經(jīng)完成守護(hù)任務(wù),由它重新啟動(dòng) 的爪哇程序運(yùn)行后會(huì)啟動(dòng)一個(gè)新的守護(hù)程序進(jìn)程,整個(gè)執(zhí)行流程轉(zhuǎn)到步驟al)。有益效果1.準(zhǔn)確確定被守護(hù)進(jìn)程在系統(tǒng)中有多個(gè)javaw. exe在運(yùn)行時(shí),本發(fā)明克服了傳統(tǒng)方法使用進(jìn)程名匹配確 定被守護(hù)進(jìn)程的弊端,能夠準(zhǔn)確確定被守護(hù)java程序?qū)嵗膉avaw. exe進(jìn)程。3.簡(jiǎn)化整體系統(tǒng)的設(shè)計(jì)把進(jìn)程守護(hù)功能部分和主體功能部分分離,因此主體應(yīng)用程序不必關(guān)心守護(hù)進(jìn)程 的實(shí)現(xiàn)細(xì)節(jié),這種模塊化的設(shè)計(jì)簡(jiǎn)化了整個(gè)應(yīng)用系統(tǒng)的開發(fā)。3.提高性能本發(fā)明沒有使用傳統(tǒng)方法的頻繁查詢機(jī)制,而是用了一種內(nèi)核狀態(tài)等待機(jī)制,該 機(jī)制告訴系統(tǒng)在等待期間,不需要給該進(jìn)程分配CPU(中央處理器)時(shí)間,節(jié)約了寶貴的CPU 時(shí)間,避免了大量系統(tǒng)資源消耗,提高了性能。4.提高健壯性守護(hù)進(jìn)程獨(dú)立為一個(gè)執(zhí)行體,也使得彼此的錯(cuò)誤不會(huì)相互影響,使整個(gè)系統(tǒng)具有 很好的健壯性。5.使用靈活,方便升級(jí)主體程序只要簡(jiǎn)單的啟動(dòng)本程序即可實(shí)現(xiàn)進(jìn)程守護(hù)功能,而不必關(guān)心其他事務(wù), 使用起來非常方便靈活。如果進(jìn)程守護(hù)模塊以后需要升級(jí),只要保證最終生成的執(zhí)行文 件名不變,對(duì)原有程序沒有任何影響,而如果主體系統(tǒng)升級(jí),只要一直使用約定的文件名即 可,這樣做保持了良好的接口性,方便系統(tǒng)升級(jí)。
圖1是現(xiàn)有的進(jìn)程守護(hù)方法。圖中SleepO過程是設(shè)定查詢操作的間隔時(shí)間,該方法先每隔一定的時(shí)間執(zhí)行查 詢以找到被守護(hù)進(jìn)程的信息;接著,再每隔一定的時(shí)間查詢?cè)撨M(jìn)程的狀態(tài)碼。這種反復(fù)查詢 機(jī)制重復(fù)許多一樣的步驟,效率低下,需要消耗大量系統(tǒng)資源。圖2是本發(fā)明的整體框架結(jié)構(gòu)。被守護(hù)的java程序啟動(dòng)守護(hù)程序進(jìn)程,建立一種父子關(guān)系;被守護(hù)的java程序停 止運(yùn)行后,守護(hù)程序進(jìn)程立即啟動(dòng)它。圖3是具體實(shí)施流程圖。
從圖中可以看出本發(fā)明的流程是線性執(zhí)行的,沒有返回的流程,這是和圖1中方 法的不同,沒有重復(fù)操作,因此效率和性能都很好;在執(zhí)行過程中使用進(jìn)程PID而不是進(jìn)程 名字來標(biāo)識(shí)父進(jìn)程,準(zhǔn)確識(shí)別被守護(hù)的java程序進(jìn)程。
具體實(shí)施例方式本發(fā)明由被守護(hù)的java程序啟動(dòng)實(shí)現(xiàn)守護(hù)功能的守護(hù)程序,守護(hù)程序運(yùn)行后開 始對(duì)其父進(jìn)程也就是被守護(hù)的java程序進(jìn)程進(jìn)行監(jiān)視,整體框架如圖2,具體流程如下該方法在被守護(hù)的爪哇程序進(jìn)程與守護(hù)程序進(jìn)程之間建立一種父子繼承關(guān)系,并 基于這種繼承關(guān)系由守護(hù)程序進(jìn)程來唯一確定被守護(hù)的爪哇程序進(jìn)程;基于被守護(hù)的爪哇 程序進(jìn)程的內(nèi)核對(duì)象狀態(tài)確定被守護(hù)的爪哇程序的運(yùn)行狀態(tài);a.基于父子繼承關(guān)系確定被守護(hù)的爪哇程序進(jìn)程的方法為步驟al).被守護(hù)的爪哇程序進(jìn)程啟動(dòng)守護(hù)程序進(jìn)程,這樣被守護(hù)的爪哇程序進(jìn) 程為父進(jìn)程,守護(hù)程序進(jìn)程成為被守護(hù)的爪哇程序進(jìn)程的子進(jìn)程,在這兩個(gè)進(jìn)程之間建立 一種繼承關(guān)系,一個(gè)子進(jìn)程只有一個(gè)父進(jìn)程,由守護(hù)程序進(jìn)程來唯一確定被守護(hù)的爪哇程 序進(jìn)程;步驟a2).守護(hù)程序進(jìn)程獲得自身進(jìn)程標(biāo)識(shí)符PID,該P(yáng)ID在守護(hù)程序進(jìn)程運(yùn)行期 間唯一地標(biāo)識(shí)守護(hù)程序進(jìn)程,使用進(jìn)程名字標(biāo)識(shí)一個(gè)進(jìn)程并不準(zhǔn)確,系統(tǒng)中同時(shí)運(yùn)行多個(gè) 同名的進(jìn)程,要獲得守護(hù)程序進(jìn)程的PID使用系統(tǒng)應(yīng)用程序編程接口即可,這樣做有利于 提高程序的移植性;步驟a3).守護(hù)程序進(jìn)程對(duì)系統(tǒng)拍快照,快照是操作系統(tǒng)為所有當(dāng)前運(yùn)行的進(jìn)程、 線程的當(dāng)前信息狀態(tài)制作的一個(gè)只讀副本,具體表現(xiàn)為一組數(shù)據(jù)結(jié)構(gòu),其中的每個(gè)結(jié)構(gòu)又 包含各個(gè)成員數(shù)據(jù),這些成員含有進(jìn)程名字、進(jìn)程執(zhí)行路徑、進(jìn)程PID和父進(jìn)程PID信息,使 用windows操作系統(tǒng)提供的函數(shù)庫Toolhelp32獲取系統(tǒng)快照;步驟a4).守護(hù)程序進(jìn)程從系統(tǒng)快照中找到包含守護(hù)程序進(jìn)程信息的數(shù)據(jù)結(jié)構(gòu), 在上一步驟獲得的一組數(shù)據(jù)結(jié)構(gòu)中,守護(hù)進(jìn)程需要搜索其中的每個(gè)數(shù)據(jù)結(jié)構(gòu),將其中的PID 成員字段和守護(hù)程序進(jìn)程在步驟a2)中獲得的自身PID進(jìn)行匹配,一旦匹配即找到包含守 護(hù)程序進(jìn)程信息的數(shù)據(jù)結(jié)構(gòu);步驟a5).保存父進(jìn)程PID即被守護(hù)的爪哇程序進(jìn)程PID,在包含守護(hù)程序進(jìn)程信 息的數(shù)據(jù)結(jié)構(gòu)中有一個(gè)成員記錄著守護(hù)程序進(jìn)程的父進(jìn)程PID,這個(gè)PID唯一地標(biāo)識(shí)被守 護(hù)的爪哇程序進(jìn)程,這樣就不必?fù)?dān)心操作系統(tǒng)中同時(shí)有多個(gè)爪哇程序進(jìn)程在運(yùn)行,將該父 進(jìn)程PID值提取并保存起來;b.基于被守護(hù)的爪哇程序進(jìn)程的內(nèi)核對(duì)象狀態(tài)確定被守護(hù)的爪哇程序的運(yùn)行狀 態(tài)的方法為步驟bl).守護(hù)程序進(jìn)程根據(jù)保存的父進(jìn)程PID通過系統(tǒng)的應(yīng)用程序編程接口打 開被守護(hù)的爪哇程序進(jìn)程,應(yīng)用程序編程接口會(huì)返回一個(gè)句柄,該句柄標(biāo)識(shí)被守護(hù)的爪哇 程序進(jìn)程的內(nèi)核對(duì)象,使用該句柄即意味著對(duì)被守護(hù)的爪哇程序進(jìn)程的操作;步驟1^2).守護(hù)程序進(jìn)程將步驟bl中返回的爪哇程序進(jìn)程內(nèi)核對(duì)象句柄傳給應(yīng)用 程序編程接口來訪問被守護(hù)的爪哇程序進(jìn)程,這時(shí)守護(hù)程序進(jìn)程進(jìn)入阻塞狀態(tài),直到被守 護(hù)的爪哇程序進(jìn)程內(nèi)核對(duì)象被觸發(fā)才繼續(xù)執(zhí)行;
步驟b3).當(dāng)被守護(hù)的爪哇程序進(jìn)程不在運(yùn)行時(shí),操作系統(tǒng)觸發(fā)該進(jìn)程的內(nèi)核對(duì) 象,守護(hù)程序進(jìn)程繼續(xù)執(zhí)行,這時(shí)守護(hù)程序進(jìn)程重新啟動(dòng)被守護(hù)的爪哇程序;步驟b4).守護(hù)程序進(jìn)程自身退出運(yùn)行,至此它已經(jīng)完成守護(hù)任務(wù),由它重新啟動(dòng) 的爪哇程序運(yùn)行后會(huì)啟動(dòng)一個(gè)新的守護(hù)程序進(jìn)程,整個(gè)執(zhí)行流程轉(zhuǎn)到步驟al)。為方便描述,假定如下應(yīng)用場(chǎng)景在使用java開發(fā)的軟件系統(tǒng)設(shè)計(jì)時(shí)有對(duì)主體應(yīng) 用程序守護(hù)的系統(tǒng)需求,并且該系統(tǒng)最終以jar格式發(fā)布給用戶使用,名字為usertest. jar,同時(shí)約定實(shí)現(xiàn)守護(hù)進(jìn)程的執(zhí)行文件名為proke印er. exe (名字不是一定的,可以根據(jù) 需要改變),其存放路徑為C: \WIND0WS\proke印er. exe (也可以將其放于別的路徑下,使用 對(duì)應(yīng)的路徑即可),為了簡(jiǎn)單起見這里假定usertest. jar和proke印er. exe位于同一目 錄下,執(zhí)行流程如圖3,具體實(shí)施方式
如下(1)在java的源代碼中,一般是初始化階段,添 加 Runtime. getRuntime (). exec 方法,并將路徑 C:\WINDOWS\prokeeper. exe 傳給它,即 Runtime. getRuntime(). exec (“ C:\WINDOWS\prokeeper.exe");(2)用戶雙擊usertest. jar運(yùn)行java應(yīng)用程序,這時(shí)系統(tǒng)會(huì)啟動(dòng)一個(gè)javaw. exe 進(jìn)程運(yùn)行應(yīng)用程序功能。這個(gè)javaw.exe進(jìn)程即為要保護(hù)的進(jìn)程,添加了(1)中的代碼后 它會(huì)啟云力守護(hù)進(jìn)程proke印er. exe。(3)proke印er. exe 進(jìn)程啟動(dòng)后,首先使用 API GetCurrentProcessld()獲得它 自己PID,這里將它保存到DWORD類型的變量selfPID中,這個(gè)值在程序運(yùn)行期間唯一標(biāo) 識(shí)proke印er. exe進(jìn)程;然后使用APICreate^ToolhelpSZSnapshot ()創(chuàng)建一個(gè)當(dāng)前系統(tǒng) 快照,獲得一個(gè)快照句柄;接著將快照句柄和PR0CESSENTRY32類型的內(nèi)存空間傳給API Process32First()獲得快照中第一個(gè)進(jìn)程信息結(jié)構(gòu),將其中的PID字段和剛才獲得的 selfPID匹配,如果匹配則找到了 proke印er. exe的進(jìn)程信息,快照遍歷結(jié)束,否則繼續(xù)調(diào) 用APIPrOCesS32NeXt()獲得下一個(gè)進(jìn)程信息結(jié)構(gòu),再將其中的PID字段和剛才的selfPID 匹配,直至找到能匹配的一個(gè)進(jìn)程信息結(jié)構(gòu),然后保存其中的th32ParentPrOCesSID字段 (即父進(jìn)程的PID),這里保存到DOWRD類型的變量paraPID中。至此已經(jīng)確定了需要守護(hù) 的進(jìn)程PID即對(duì)應(yīng)于usertest. jar的javaw. exe進(jìn)程PID。(4)在得到一個(gè)正在運(yùn)行的進(jìn)程PID之后,就可以用該P(yáng)ID訪問該進(jìn)程對(duì)象 了。這個(gè) API 函數(shù)是 OpenProcess 0,這里的調(diào)用形式為 OpenProcess (PR0CESS_ALL_ ACCESS, FALSE, paraPID),該函數(shù)返回paraPID標(biāo)識(shí)的進(jìn)程內(nèi)核對(duì)象的句柄paraH即對(duì) 應(yīng)于usertest. jar的javaw. exe進(jìn)程內(nèi)核對(duì)象,注意第一個(gè)參數(shù)必須為PR0CESS_ALL_ ACCESS,否則無法獲得相應(yīng)的訪問權(quán)限導(dǎo)致監(jiān)視內(nèi)核對(duì)象狀態(tài)失敗。獲得進(jìn)程內(nèi)核對(duì) 象的句柄之后,就可以使用等待函數(shù)使守護(hù)進(jìn)程處于等待狀態(tài)直到指定的內(nèi)核對(duì)象被觸 發(fā),即等待對(duì)應(yīng)于usertest. jar的javaw. exe進(jìn)程結(jié)束,那時(shí)相應(yīng)進(jìn)程內(nèi)核對(duì)象被觸 發(fā)。等待函數(shù)API為Waiti^orSingleObjectO,在這里第一個(gè)參數(shù)為paraH,表示等待該 對(duì)象被觸發(fā),第二個(gè)參數(shù)為INFINIT,這告訴系統(tǒng),調(diào)用進(jìn)程愿意永遠(yuǎn)等待,沒有超時(shí)時(shí) 間。一旦對(duì)應(yīng)于usertest. jar的javaw. exe進(jìn)程結(jié)束,其進(jìn)程內(nèi)核對(duì)象被觸發(fā),這時(shí) WaitForSingleObjectO返回,守護(hù)進(jìn)程proke印er. exe從等待狀態(tài)喚醒。這時(shí)可以對(duì) WaitForSingleObject ()的返回值進(jìn)程判斷,如果等于WAIT_0BJECT_0,說明等待的內(nèi)核對(duì) 象被觸發(fā)即對(duì)應(yīng)于usertest. jar的javaw. exe進(jìn)程結(jié)束了。(5)當(dāng)對(duì)應(yīng)于usertest. jar的javaw. exe進(jìn)程結(jié)束了,守護(hù)進(jìn)程就需要馬上重新啟動(dòng)該usertest. jar應(yīng)用程序。在windows中啟動(dòng)一個(gè)jar程序就和啟動(dòng)一個(gè)exe程序 類似,可以使用API ShellExecuteO來實(shí)現(xiàn),第一個(gè)參數(shù)、第四個(gè)參數(shù)和第五個(gè)參數(shù)設(shè)為 NULL,第二個(gè)參數(shù)為"open"表示對(duì)文件執(zhí)行打開操作,第三個(gè)參數(shù)為要啟動(dòng)的文件路徑, 這里已經(jīng)假定在同一目錄下為〃 .\\usertest. jar",最后一個(gè)參數(shù)設(shè)為SW_SH0WN0RMAL
表示正常顯示程序。最后守護(hù)進(jìn)程就退出,usertest. jar啟動(dòng)后,執(zhí)行流程又轉(zhuǎn)到步驟 ⑵。
權(quán)利要求
1. 一種基于進(jìn)程間繼承關(guān)系的爪哇程序進(jìn)程守護(hù)方法,其特征在于該方法在被守護(hù)的 爪哇程序進(jìn)程與守護(hù)程序進(jìn)程之間建立一種父子繼承關(guān)系,并基于這種繼承關(guān)系由守護(hù)程 序進(jìn)程來唯一確定被守護(hù)的爪哇程序進(jìn)程;基于被守護(hù)的爪哇程序進(jìn)程的內(nèi)核對(duì)象狀態(tài)確 定被守護(hù)的爪哇程序的運(yùn)行狀態(tài);a.基于父子繼承關(guān)系確定被守護(hù)的爪哇程序進(jìn)程的方法為步驟al).被守護(hù)的爪哇程序進(jìn)程啟動(dòng)守護(hù)程序進(jìn)程,這樣被守護(hù)的爪哇程序進(jìn)程為 父進(jìn)程,守護(hù)程序進(jìn)程成為被守護(hù)的爪哇程序進(jìn)程的子進(jìn)程,在這兩個(gè)進(jìn)程之間建立一種 繼承關(guān)系,一個(gè)子進(jìn)程只有一個(gè)父進(jìn)程,由守護(hù)程序進(jìn)程來唯一確定被守護(hù)的爪哇程序進(jìn) 程;步驟a2).守護(hù)程序進(jìn)程獲得自身進(jìn)程標(biāo)識(shí)符PID,該P(yáng)ID在守護(hù)程序進(jìn)程運(yùn)行期間唯 一地標(biāo)識(shí)守護(hù)程序進(jìn)程,使用進(jìn)程名字標(biāo)識(shí)一個(gè)進(jìn)程并不準(zhǔn)確,系統(tǒng)中同時(shí)運(yùn)行多個(gè)同名 的進(jìn)程,要獲得守護(hù)程序進(jìn)程的PID使用系統(tǒng)應(yīng)用程序編程接口即可,這樣做有利于提高 程序的移植性;步驟a3).守護(hù)程序進(jìn)程對(duì)系統(tǒng)拍快照,快照是操作系統(tǒng)為所有當(dāng)前運(yùn)行的進(jìn)程、線程 的當(dāng)前信息狀態(tài)制作的一個(gè)只讀副本,具體表現(xiàn)為一組數(shù)據(jù)結(jié)構(gòu),其中的每個(gè)結(jié)構(gòu)又包含 各個(gè)成員數(shù)據(jù),這些成員含有進(jìn)程名字、進(jìn)程執(zhí)行路徑、進(jìn)程PID和父進(jìn)程PID信息,使用 windows操作系統(tǒng)提供的函數(shù)庫Toolhelp32獲取系統(tǒng)快照;步驟a4).守護(hù)程序進(jìn)程從系統(tǒng)快照中找到包含守護(hù)程序進(jìn)程信息的數(shù)據(jù)結(jié)構(gòu),在上 一步驟獲得的一組數(shù)據(jù)結(jié)構(gòu)中,守護(hù)進(jìn)程需要搜索其中的每個(gè)數(shù)據(jù)結(jié)構(gòu),將其中的PID成 員字段和守護(hù)程序進(jìn)程在步驟a2)中獲得的自身PID進(jìn)行匹配,一旦匹配即找到包含守護(hù) 程序進(jìn)程信息的數(shù)據(jù)結(jié)構(gòu);步驟a5).保存父進(jìn)程PID即被守護(hù)的爪哇程序進(jìn)程PID,在包含守護(hù)程序進(jìn)程信息的 數(shù)據(jù)結(jié)構(gòu)中有一個(gè)成員記錄著守護(hù)程序進(jìn)程的父進(jìn)程PID,這個(gè)PID唯一地標(biāo)識(shí)被守護(hù)的 爪哇程序進(jìn)程,這樣就不必?fù)?dān)心操作系統(tǒng)中同時(shí)有多個(gè)爪哇程序進(jìn)程在運(yùn)行,將該父進(jìn)程 PID值提取并保存起來;b.基于被守護(hù)的爪哇程序進(jìn)程的內(nèi)核對(duì)象狀態(tài)確定被守護(hù)的爪哇程序的運(yùn)行狀態(tài)的 方法為步驟bl).守護(hù)程序進(jìn)程根據(jù)保存的父進(jìn)程PID通過系統(tǒng)的應(yīng)用程序編程接口打 開被守護(hù)的爪哇程序進(jìn)程,應(yīng)用程序編程接口會(huì)返回一個(gè)句柄,該句柄標(biāo)識(shí)被守護(hù)的 爪哇程序進(jìn)程的內(nèi)核對(duì)象,使用該句柄即意味著對(duì)被守護(hù)的爪哇程序進(jìn)程的操作;步驟1^2).守護(hù)程序進(jìn)程將步驟bl中返回的爪哇程序進(jìn)程內(nèi)核對(duì)象句柄傳給應(yīng)用程序 編程接口來訪問被守護(hù)的爪哇程序進(jìn)程,這時(shí)守護(hù)程序進(jìn)程進(jìn)入阻塞狀態(tài),直到被守護(hù)的 爪哇程序進(jìn)程內(nèi)核對(duì)象被觸發(fā)才繼續(xù)執(zhí)行;步驟b3).當(dāng)被守護(hù)的爪哇程序進(jìn)程不在運(yùn)行時(shí),操作系統(tǒng)觸發(fā)該進(jìn)程的內(nèi)核對(duì)象,守 護(hù)程序進(jìn)程繼續(xù)執(zhí)行,這時(shí)守護(hù)程序進(jìn)程重新啟動(dòng)被守護(hù)的爪哇程序;步驟b4).守護(hù)程序進(jìn)程自身退出運(yùn)行,至此它已經(jīng)完成守護(hù)任務(wù),由它重新啟動(dòng)的爪 哇程序運(yùn)行后會(huì)啟動(dòng)一個(gè)新的守護(hù)程序進(jìn)程,整個(gè)執(zhí)行流程轉(zhuǎn)到步驟al)。
全文摘要
基于進(jìn)程間繼承關(guān)系的爪哇程序進(jìn)程守護(hù)方法是一種在windows系統(tǒng)(一種操作系統(tǒng)的名稱)中,針對(duì)爪哇程序(使用爪哇編程語言開發(fā)的程序,以下稱java程序)進(jìn)行守護(hù)的方法。主要用來解決被守護(hù)的java程序進(jìn)程的鑒別和確定,并對(duì)該java程序的運(yùn)行狀態(tài)進(jìn)行監(jiān)控,防止其意外終止運(yùn)行,該方法在被守護(hù)的爪哇程序進(jìn)程與守護(hù)程序進(jìn)程之間建立一種父子繼承關(guān)系,并基于這種繼承關(guān)系由守護(hù)程序進(jìn)程來唯一確定被守護(hù)的爪哇程序進(jìn)程;基于被守護(hù)的爪哇程序進(jìn)程的內(nèi)核對(duì)象狀態(tài)確定被守護(hù)的爪哇程序的運(yùn)行狀態(tài)。
文檔編號(hào)G06F21/22GK102103676SQ20111004904
公開日2011年6月22日 申請(qǐng)日期2011年2月28日 優(yōu)先權(quán)日2011年2月28日
發(fā)明者孫力娟, 張偉, 李偉, 李鵬, 王汝傳, 黃海平 申請(qǐng)人:南京郵電大學(xué)