本公開涉及計算機技術(shù)領(lǐng)域,具體地,涉及一種內(nèi)存管理方法及設(shè)備。
背景技術(shù):
內(nèi)存泄漏是應(yīng)用程序中很常見的問題之一。現(xiàn)在隨著計算機科學(xué)的發(fā)展,很多高級編程語言采用動態(tài)內(nèi)存垃圾回收機制,編程語言虛擬機自動管理內(nèi)存,這就大大減少了內(nèi)存泄漏的問題。但是對于C/C++語言,由于其具有適用于嵌入式系統(tǒng)開發(fā)、性能高、可靈活掌握內(nèi)存等特點,依然有著不可替代性。C/C++語言具有指針引用的特點,應(yīng)用程序申請的內(nèi)存經(jīng)過多重引用,容易出現(xiàn)內(nèi)存泄露的情況,而C/C++語言程序沒有內(nèi)存垃圾回收機制,需要用戶手動管理內(nèi)存,即C/C++應(yīng)用程序的代碼需要手動控制內(nèi)存申請和釋放。
目前已經(jīng)有了一些分析內(nèi)容泄漏的工具,即內(nèi)存分析程序。但這些內(nèi)存分析程序,一般是運行在X86體系結(jié)構(gòu)的主機上,不適用于PowerPC,MIPS,ARM等各種嵌入式處理器環(huán)境,導(dǎo)致嵌入式環(huán)境內(nèi)存泄漏問題調(diào)試很困難。
技術(shù)實現(xiàn)要素:
為克服相關(guān)技術(shù)中存在的問題,本公開提供一種內(nèi)存管理方法及設(shè)備。
根據(jù)本公開實施例的第一方面,提供一種內(nèi)存管理方法,包括:
接收來自應(yīng)用程序的內(nèi)存調(diào)用請求;
根據(jù)所述內(nèi)存調(diào)用請求,從LD_PRELOAD環(huán)境變量所指定的動態(tài)庫調(diào)用相應(yīng)的API來進行內(nèi)存調(diào)用;以及
記錄與所述內(nèi)存調(diào)用請求相關(guān)的信息,所述內(nèi)存調(diào)用請求相關(guān)的信息包含所述內(nèi)存調(diào)用請求所申請的內(nèi)存大小及所述應(yīng)用程序的調(diào)用函數(shù)的地址。
根據(jù)本公開實施例的第二方面,提供一種內(nèi)存管理裝置,包括:
接收單元,用于接收來自應(yīng)用程序的內(nèi)存調(diào)用請求;
動態(tài)庫確定單元,用于根據(jù)所述內(nèi)存調(diào)用請求,從LD_PRELOAD環(huán)境變量所指定的動態(tài)庫調(diào)用相應(yīng)的API來進行內(nèi)存調(diào)用;以及
記錄單元,用于記錄與所述內(nèi)存調(diào)用請求相關(guān)的信息,所述內(nèi)存調(diào)用請求相關(guān)的信息包含所述內(nèi)存調(diào)用請求所申請的內(nèi)存大小及所述應(yīng)用程序的調(diào)用函數(shù)的地址。
本公開的實施例提供的技術(shù)方案可以包括以下有益效果:LD_PRELOAD環(huán)境變量所指定的動態(tài)庫提供了C語言內(nèi)存管理函數(shù)常用的API的替換函數(shù),這些替換函數(shù)在實際名稱及功能方面與常規(guī)GlibC的內(nèi)存申請API是一樣的,只是在其中增加了有關(guān)與記錄與所述內(nèi)存調(diào)用請求相關(guān)的信息,從而無需修改應(yīng)用程序,僅需在啟動應(yīng)用程序的腳本中使用LD_PERLOAD環(huán)境變量指定動態(tài)庫,之后使用該動態(tài)庫內(nèi)的含內(nèi)存調(diào)用請求相關(guān)信息記錄功能的代碼的API來替代C語言內(nèi)存管理函數(shù)的常用內(nèi)存調(diào)用API從而應(yīng)用程序在進行內(nèi)存調(diào)用時,既可以實現(xiàn)內(nèi)存調(diào)用或分配,又可記錄與該內(nèi)存調(diào)用相關(guān)的信息,達(dá)到內(nèi)存調(diào)用及管理的目的。此外,本公開實施例的動態(tài)庫是充分地利用了Glibc的基礎(chǔ)特性,可移植性較強,示例性地,可以完整地移植到各種嵌入式平臺,且在交叉編譯過程中不會出現(xiàn)問題,實現(xiàn)有效移植。
應(yīng)當(dāng)理解的是,以上的一般描述和后文的細(xì)節(jié)描述僅是示例性和解釋性的,并不能限制本公開。
附圖說明
附圖是用來提供對本公開的進一步理解,并且構(gòu)成說明書的一部分,與下面的具體實施方式一起用于解釋本公開,但并不構(gòu)成對本公開的限制。在附圖中:
圖1為本公開一實施例提供的內(nèi)存管理方法的流程圖;
圖2A為相關(guān)技術(shù)中應(yīng)用程序?qū)τ趦?nèi)存申請API的調(diào)用方式的示意圖;
圖2B為本公開中應(yīng)用程序?qū)τ趦?nèi)存申請API的調(diào)用方式的示意圖;
圖3為本公開一實施例的內(nèi)存申請流程圖;
圖4為本公開另一實施例的內(nèi)存管理方法的流程圖;
圖5為本公開一實施例提供的內(nèi)存管理設(shè)備的結(jié)構(gòu)框圖;以及
圖6為本公開另一實施例提供的內(nèi)存管理設(shè)備的結(jié)構(gòu)框圖。
具體實施方式
這里將詳細(xì)地對示例性實施例進行說明,其示例表示在附圖中。下面的描述涉及附圖時,除非另有表示,不同附圖中的相同數(shù)字表示相同或相似的要素。以下示例性實施例中所描述的實施方式并不代表與本公開相一致的所有實施方式。相反,它們僅是與如所附權(quán)利要求書中所詳述的、本公開的一些方面相一致的裝置和方法的例子。
以下結(jié)合附圖對本公開提供的內(nèi)存管理方法及設(shè)備的具體實施方式進行詳細(xì)說明。應(yīng)當(dāng)理解的是,此處所描述的具體實施方式僅用于說明和解釋本公開,并不用于限制本公開。
圖1為本公開一實施例提供的內(nèi)存管理方法的流程圖。如圖1所示,本公開一實施例提供了一種內(nèi)存管理方法,該方法包括:
步驟S110,接收來自應(yīng)用程序的內(nèi)存調(diào)用請求。
在本步驟中,內(nèi)存調(diào)用請求可以包括應(yīng)用程序的標(biāo)識符(例如,應(yīng)用程序的名稱、地址等)、請求調(diào)用的內(nèi)存大小(例如,請求調(diào)用128字節(jié)的內(nèi)存)。
步驟S120,根據(jù)內(nèi)存調(diào)用請求,從LD_PRELOAD環(huán)境變量所指定的動態(tài)庫調(diào)用相應(yīng)的API來進行內(nèi)存調(diào)用。
LD_PRELOAD是個環(huán)境變量,它可以影響應(yīng)用程序運行時的鏈接(Runtime linker),允許用戶定義在程序運行前優(yōu)先加載的動態(tài)庫(或者動態(tài)鏈接庫),從而可以有選擇性的載入不同動態(tài)鏈接庫中的相同函數(shù)。通過LD_PRELOAD,可以在應(yīng)用程序和其動態(tài)庫(或者動態(tài)鏈接庫)的中間加載別的動態(tài)庫(或者動態(tài)鏈接庫),甚至覆蓋正常的函數(shù)庫。例如,在本步驟中,可以自定義的例如C語言內(nèi)存管理函數(shù)常用的malloc、calloc、realloc、free等函數(shù),并將自定義的內(nèi)存管理函數(shù)編譯成動態(tài)庫,通過LD_PRELOAD在應(yīng)用程序運行前優(yōu)先加載自定義的內(nèi)存管理函數(shù)(或者內(nèi)存申請API),則在應(yīng)用程序運行過程中可以調(diào)用該自定義的內(nèi)存管理函數(shù)。
在發(fā)明實施例中,自定義的內(nèi)存管理函數(shù)(或者內(nèi)存申請API)在實際名稱及功能方面與常規(guī)GlibC的內(nèi)存管理函數(shù)(或者內(nèi)存申請API)是一樣的,但自定義的內(nèi)存管理函數(shù)(或者內(nèi)存申請API)增加了用于記錄與內(nèi)存調(diào)用請求相關(guān)的信息,因此,在通過該自定義的內(nèi)存管理函數(shù)進行內(nèi)存申請時,可以記錄內(nèi)存調(diào)用的相關(guān)信息,例如內(nèi)存大小、應(yīng)用程序名稱、應(yīng)用程序的調(diào)用函數(shù)地址等等。因此,無需修改應(yīng)用程序,即可實現(xiàn)內(nèi)存記錄和內(nèi)存調(diào)試。
通過LD_PRELOAD加載內(nèi)存管理函數(shù)動態(tài)庫,可以加載自定義的或者功能、效果上更優(yōu)的函數(shù)。在運行應(yīng)用程序的腳本過程中使用LD_PERLOAD環(huán)境變量指定動態(tài)庫,以調(diào)用自定義的內(nèi)存管理函數(shù),將自定義的內(nèi)存管理函數(shù)替代C語言內(nèi)存管理函數(shù)的常用內(nèi)存管理函數(shù)(例如,malloc,calloc,realloc,free等),即可以實現(xiàn)內(nèi)存調(diào)用或分配,且可記錄與該內(nèi)存調(diào)用相關(guān)的信息,達(dá)到內(nèi)存調(diào)用及管理的目的。此外,通過LD_PRELOAD加載動態(tài)庫實現(xiàn)內(nèi)存調(diào)用,可以方便地對動態(tài)庫中的內(nèi)存管理函數(shù)優(yōu)化或者增加調(diào)試,可以根據(jù)應(yīng)用需求靈活地修改動態(tài)庫中的內(nèi)存管理函數(shù)。
為了本領(lǐng)域技術(shù)人員能夠更清楚、準(zhǔn)確地理解本發(fā)明實施例的技術(shù)方案,下面通過附圖及相關(guān)描述對本發(fā)明實施例、現(xiàn)有技術(shù)的實施例進一步說明。
圖2A為相關(guān)技術(shù)中應(yīng)用程序?qū)τ趦?nèi)存申請API的調(diào)用方式的示意圖,圖2B為本公開中應(yīng)用程序?qū)τ趦?nèi)存申請API的調(diào)用方式的示意圖。如圖2A所示,相關(guān)技術(shù)中,在接收到來自應(yīng)用程序的內(nèi)存調(diào)用請求時,直接對Glibc庫中的內(nèi)存申請API(內(nèi)存管理函數(shù))進行調(diào)用,例如Glibc庫中提供的常用的malloc,calloc,realloc,free等常用內(nèi)存申請API。如圖2B所示,在接收到來自應(yīng)用程序的內(nèi)存調(diào)用請求時,可以通過LD_PRELOAD環(huán)境變量加載指定的動態(tài)庫,該動態(tài)庫可以提供自定義的內(nèi)存管理函數(shù)(或者內(nèi)存申請API)例如malloc,calloc,realloc,free等,從而從動態(tài)庫調(diào)用自定義的內(nèi)存管理函數(shù),實現(xiàn)內(nèi)存調(diào)用。本公開實施例的動態(tài)庫是充分地利用了Glibc的基礎(chǔ)特性,可移植性較強,示例性地,可以完整地移植到各種嵌入式平臺,且在交叉編譯過程中不會出現(xiàn)問題,實現(xiàn)有效移植。
步驟S130,記錄與內(nèi)存調(diào)用請求相關(guān)的信息,其中,內(nèi)存調(diào)用請求相關(guān)的信息包含內(nèi)存調(diào)用請求所申請的內(nèi)存大小及應(yīng)用程序的調(diào)用函數(shù)的地址。
當(dāng)然本公開并不限于此,在本步驟中還可記錄與應(yīng)用程序的調(diào)用函數(shù)的名稱和/或其他希望記錄的與內(nèi)存調(diào)用請求相關(guān)的信息。
圖3為本公開一實施例的內(nèi)存申請流程圖。為了便于后續(xù)敘述,對于本公開中的內(nèi)存申請API(或者內(nèi)存管理函數(shù)),敘述時增加“my_”前綴,比如my_malloc函數(shù),其實指的是本公開內(nèi)存管理動態(tài)庫中的malloc函數(shù);my_free函數(shù),指的是本公開動態(tài)庫中的free函數(shù)。
如圖3所示,以調(diào)用my_malloc函數(shù)申請內(nèi)存為例對本公開進行了示例性說明。在應(yīng)用程序發(fā)起內(nèi)存調(diào)用請求時,可以通過LD_PRELOAD環(huán)境變量所指定的動態(tài)庫調(diào)用內(nèi)存管理函數(shù),例如調(diào)用動態(tài)庫中的my_malloc函數(shù)。在本公開一實施例中,通過調(diào)用my_malloc函數(shù)為應(yīng)用程序申請內(nèi)存時,該my_malloc函數(shù)會為所申請的內(nèi)存增加特定的頭部信息和尾部信息,其中,頭部信息和尾部信息可以用于在內(nèi)存調(diào)試過程中檢測內(nèi)存是否越界,以及記錄應(yīng)用程序本次申請的內(nèi)存的大小、應(yīng)用程序中調(diào)用內(nèi)存的調(diào)用函數(shù)的地址等,從而以用于管理應(yīng)用程序申請內(nèi)存的記錄。
根據(jù)本公開一實施例,所分配的內(nèi)存包含設(shè)置于其頭部的頭部魔術(shù)字及設(shè)置于其尾部的尾部魔術(shù)字,示例性地,可以通過動態(tài)庫中的自定義的內(nèi)存管理函數(shù)對分配的內(nèi)存設(shè)置,以設(shè)置該內(nèi)存的頭部魔術(shù)字和尾部魔術(shù)字。
示例性地,my_malloc函數(shù)通過對以下結(jié)構(gòu)體進行設(shè)置,以實現(xiàn)內(nèi)存調(diào)用、內(nèi)存調(diào)用信息記錄等,以用于管理應(yīng)用程序申請內(nèi)存的記錄。
1、頭部信息
2、尾部信息
如圖3所示,如果應(yīng)用程序要申請128字節(jié)的內(nèi)存,則其需執(zhí)行以下操作:
a)應(yīng)用程序通過LD_PRELOAD環(huán)境變量所指定的動態(tài)庫調(diào)用my_malloc函數(shù)以申請128字節(jié)的內(nèi)存;
b)my_malloc函數(shù)實際申請大小為(128+MALLOC_HEADER+MALLOC_TAILER)大小的內(nèi)存,即申請的內(nèi)存大小除了應(yīng)用程序申請的內(nèi)存的大小外,還包括頭部信息和尾部信息所占用的內(nèi)存空間的大??;
c)my_malloc函數(shù)對MALLOC_HEADER和MALLOC_TAILER結(jié)構(gòu)體進行設(shè)置,設(shè)置動作包括:記錄應(yīng)用程序本次申請的內(nèi)存大小128字節(jié)、記錄應(yīng)用程序中的本次申請內(nèi)存的調(diào)用函數(shù)的地址、設(shè)置內(nèi)存頭部魔術(shù)字和內(nèi)存尾部魔術(shù)字;
d)my_malloc函數(shù)返回申請的實際應(yīng)用程序申請的內(nèi)存,即如如圖4所示的MALLOC_HEADER后面的128字節(jié)。
需要說明的是,在上述my_malloc函數(shù)對MALLOC_HEADER和MALLOC_TAILER設(shè)置時,一個關(guān)鍵的步驟就是如何獲得應(yīng)用程序中調(diào)用my_malloc函數(shù)的調(diào)用者函數(shù)是哪個,這也是內(nèi)存調(diào)試中最重要的元素。在本公開一實施例中,可以利用Glibc庫提供的builtin_return_address內(nèi)置函數(shù),得到my_malloc函數(shù)的調(diào)用者的函數(shù)地址(16進制格式),并可由此獲得my_malloc函數(shù)的調(diào)用者的函數(shù)名稱。
圖4為本公開另一實施例的內(nèi)存管理方法的流程圖。如圖4所示的本公開另一實施例的內(nèi)存管理方法還包含以下步驟:
步驟S410,接收來自應(yīng)用程序的內(nèi)存調(diào)用請求。
例如,該內(nèi)存調(diào)用請求可請求調(diào)用128字節(jié)的內(nèi)存。本步驟與前述實施例中的步驟S110的原理、實現(xiàn)過程及效果相同,為了簡潔在此不再贅述。
步驟S420,根據(jù)內(nèi)存調(diào)用請求,從LD_PRELOAD環(huán)境變量所指定的動態(tài)庫調(diào)用相應(yīng)的API來進行內(nèi)存調(diào)用。
本步驟與前述實施例中的步驟S120的原理、實現(xiàn)過程及效果相同,為了簡潔在此不再贅述。
步驟S430,記錄與內(nèi)存調(diào)用請求相關(guān)的信息,內(nèi)存調(diào)用請求相關(guān)的信息包含內(nèi)存調(diào)用請求所申請的內(nèi)存大小及應(yīng)用程序的調(diào)用函數(shù)的地址。
當(dāng)然本公開并不限于此,還可記錄與應(yīng)用程序的調(diào)用函數(shù)的名稱和/或其他希望記錄的與內(nèi)存調(diào)用請求相關(guān)的信息。
本步驟與前述實施例中的步驟S130的原理、實現(xiàn)過程及效果相同,為了簡潔在此不再贅述。
S440,通過哈希表管理內(nèi)存調(diào)用請求相關(guān)的信息,其中,哈希表的任一表項包括應(yīng)用程序的內(nèi)存申請統(tǒng)計及應(yīng)用程序的調(diào)用函數(shù)的地址的對應(yīng)關(guān)系。
其中,可通過哈希表管理內(nèi)存調(diào)用請求相關(guān)的信息,例如管理應(yīng)用程序中本次調(diào)用內(nèi)存的調(diào)用者函數(shù)的地址,管理應(yīng)用程序的內(nèi)存申請統(tǒng)計。示例性地,為了管理應(yīng)用程序的內(nèi)存申請統(tǒng)計,建立一個哈希表,哈希表的被哈希的關(guān)鍵字字段為應(yīng)用程序中本次調(diào)用內(nèi)存的調(diào)用者函數(shù)的地址,哈希表的內(nèi)容為該調(diào)用者函數(shù)申請內(nèi)存的總統(tǒng)計。
在一個實施例中,哈希表管理可包括以下操作:在接收到來自應(yīng)用程序的內(nèi)存調(diào)用請求時,根據(jù)應(yīng)用程序的調(diào)用函數(shù)(調(diào)用者函數(shù))的地址在哈希表內(nèi)查找,以確定在哈希表中是否存儲有應(yīng)用程序的調(diào)用函數(shù)的地址。當(dāng)哈希表存儲有應(yīng)用程序的調(diào)用函數(shù)的地址時,在對應(yīng)表項的內(nèi)存申請統(tǒng)計加入本次申請的內(nèi)存大小。
在另一個實施例中,在接收到來自應(yīng)用程序的內(nèi)存釋放請求時,根據(jù)應(yīng)用程序的調(diào)用函數(shù)的地址在哈希表內(nèi)查找,以確定在哈希表中是否存儲有應(yīng)用程序的調(diào)用函數(shù)的地址;當(dāng)哈希表存儲有應(yīng)用程序的調(diào)用函數(shù)的地址時,從對應(yīng)表項的內(nèi)存申請統(tǒng)計減去本次釋放的內(nèi)存大小。如果減去本次釋放的內(nèi)存大小之后對應(yīng)表項的內(nèi)存申請統(tǒng)計為零,則可刪除該表項。
S450,遍歷所哈希表,獲取內(nèi)存調(diào)用請求相關(guān)的信息,以進行內(nèi)存泄漏調(diào)試。
用戶可通過該遍歷該哈希表以獲取應(yīng)用程序申請內(nèi)存的全部信息。通過遍歷內(nèi)存申請管理的哈希表,可將申請內(nèi)存的應(yīng)用程序的調(diào)用函數(shù)的地址按照該函數(shù)申請總內(nèi)存的大小從大到小排序,從而可快速地獲取應(yīng)用程序申請內(nèi)存的全部信息,進而可以對應(yīng)用程序的內(nèi)存進行調(diào)試,避免內(nèi)存泄漏問題出現(xiàn)。通過遍歷哈希表,可以隨時輸出打印應(yīng)用程序的內(nèi)存使用信息,使內(nèi)存調(diào)試更為靈活方便。
圖5為本公開一實施例提供的內(nèi)存管理設(shè)備的結(jié)構(gòu)框圖。如圖5所示,本公開一實施例還提供一種內(nèi)存管理設(shè)備,該設(shè)備包括:接收單元,用于接收來自應(yīng)用程序的內(nèi)存調(diào)用請求;動態(tài)庫確定單元,用于根據(jù)內(nèi)存調(diào)用請求,從LD_PRELOAD環(huán)境變量所指定的動態(tài)庫調(diào)用相應(yīng)的API來進行內(nèi)存調(diào)用;以及記錄單元,用于記錄與內(nèi)存調(diào)用請求相關(guān)的信息,內(nèi)存調(diào)用請求相關(guān)的信息包含內(nèi)存調(diào)用請求所申請的內(nèi)存大小及應(yīng)用程序的調(diào)用函數(shù)的地址。
可選的,所分配的內(nèi)存包含設(shè)置于其頭部的頭部魔術(shù)字及設(shè)置于其尾部的尾部魔術(shù)字。
圖6為本公開另一實施例提供的內(nèi)存管理設(shè)備的結(jié)構(gòu)框圖。與圖5所示的結(jié)構(gòu)框圖不同之處在于,該圖6所示的設(shè)備還包括:管理單元,用于通過哈希表管理內(nèi)存調(diào)用請求相關(guān)的信息,哈希表的任一表項包括應(yīng)用程序的內(nèi)存申請統(tǒng)計及應(yīng)用程序的調(diào)用函數(shù)的地址的對應(yīng)關(guān)系。
可選的,管理單元包括:第一確定模塊,用于在接收到來自應(yīng)用程序的內(nèi)存調(diào)用請求時,根據(jù)應(yīng)用程序的調(diào)用函數(shù)的地址在哈希表內(nèi)查找,以確定在哈希表中是否存儲有應(yīng)用程序的調(diào)用函數(shù)的地址;內(nèi)存統(tǒng)計模塊,用于當(dāng)哈希表存儲有應(yīng)用程序的調(diào)用函數(shù)的地址時,在對應(yīng)表項的內(nèi)存申請統(tǒng)計加入本次申請的內(nèi)存大??;或者,第二確定模塊,用于在接收到來自應(yīng)用程序的內(nèi)存釋放請求時,根據(jù)應(yīng)用程序的調(diào)用函數(shù)的地址在哈希表內(nèi)查找,以確定在哈希表中是否存儲有應(yīng)用程序的調(diào)用函數(shù)的地址;內(nèi)存釋放模塊,用于當(dāng)哈希表存儲有應(yīng)用程序的調(diào)用函數(shù)的地址時,從對應(yīng)表項的內(nèi)存申請統(tǒng)計減去本次釋放的內(nèi)存大小。
可選的,該內(nèi)存管理設(shè)備還包括:遍歷單元,遍歷哈希表,獲取內(nèi)存調(diào)用請求相關(guān)的信息,以進行內(nèi)存泄漏調(diào)試。
關(guān)于上述實施例中的裝置,其中各個模塊執(zhí)行操作的具體方式已經(jīng)在有關(guān)該方法的實施例中進行了詳細(xì)描述,此處將不做詳細(xì)闡述說明。
雖然上述以嵌入式系統(tǒng)的一般運行環(huán)境Linux操作系統(tǒng)以及基本的C語言運行環(huán)境GLibC C語言庫為例對本公開進行了示例性說明,但本公開并不限于此,本公開可適用于任何其他可運行本公開的思想的環(huán)境中。
本領(lǐng)域技術(shù)人員可以理解實現(xiàn)上述實施例方法中的全部或部分步驟是可以通過程序來指令相關(guān)的硬件來完成,該程序存儲在一個存儲介質(zhì)中,包括若干指令用以使得一個(可以是單片機,芯片等)或處理器(processor)執(zhí)行本公開各個實施例所述方法的全部或部分步驟。而前述的存儲介質(zhì)包括:U盤、移動硬盤、只讀存儲器(ROM,Read-Only Memory)、隨機存取存儲器(RAM,Random Access Memory)、磁碟或者光盤等各種可以存儲程序代碼的介質(zhì)。
以上結(jié)合附圖詳細(xì)描述了本公開的優(yōu)選實施方式,但是,本公開并不限于上述實施方式中的具體細(xì)節(jié),在本公開的技術(shù)構(gòu)思范圍內(nèi),可以對本公開的技術(shù)方案進行多種簡單變型,這些簡單變型均屬于本公開的保護范圍。
另外需要說明的是,在上述具體實施方式中所描述的各個具體技術(shù)特征,在不矛盾的情況下,可以通過任何合適的方式進行組合。為了避免不必要的重復(fù),本公開對各種可能的組合方式不再另行說明。
本領(lǐng)域技術(shù)人員在考慮說明書及實踐這里公開的發(fā)明后,將容易想到本公開的其它實施方案。本公開旨在涵蓋本公開的任何變型、用途或者適應(yīng)性變化,這些變型、用途或者適應(yīng)性變化遵循本公開的一般性原理并包括本公開未公開的本技術(shù)領(lǐng)域中的公知常識或慣用技術(shù)手段。說明書和實施例僅被視為示例性的,本公開的真正范圍和精神由下面的權(quán)利要求指出。
應(yīng)當(dāng)理解的是,本公開并不局限于上面已經(jīng)描述并在附圖中示出的精確結(jié)構(gòu),并且可以在不脫離其范圍進行各種修改和改變。本公開的范圍僅由所附的權(quán)利要求來限制。