• <tr id="yyy80"></tr>
  • <sup id="yyy80"></sup>
  • <tfoot id="yyy80"><noscript id="yyy80"></noscript></tfoot>
  • 99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

    利用內(nèi)核腳本執(zhí)行引擎優(yōu)化系統(tǒng)調(diào)用過程

    2021-04-20 06:34:04夏盛明
    電子技術(shù)與軟件工程 2021年3期
    關(guān)鍵詞:腳本內(nèi)核調(diào)用

    夏盛明

    (福州理工學院計算與信息科學學院 福建省福州市 350000)

    在Linux 系統(tǒng),進程訪問內(nèi)核服務,調(diào)用系統(tǒng)調(diào)用的過程中需要進行用戶態(tài)和內(nèi)核態(tài)的轉(zhuǎn)換。進程執(zhí)行系統(tǒng)調(diào)用進行狀態(tài)切換是個耗時的過程,目前在改進Linux 系統(tǒng)調(diào)用的性能已有許多研究工作。如multi-call 機制[1],在內(nèi)核中實現(xiàn)了系統(tǒng)調(diào)用代理,通過將用戶進程多次執(zhí)行的系統(tǒng)調(diào)用函數(shù)進行合并,組成系統(tǒng)調(diào)用函數(shù)數(shù)組,在一次系統(tǒng)調(diào)用過程中,由內(nèi)核系統(tǒng)調(diào)用代理執(zhí)行函數(shù)數(shù)組中的函數(shù)。這種方式減少了用戶進程執(zhí)行系統(tǒng)調(diào)用時的狀態(tài)轉(zhuǎn)換次數(shù),但是,multi-call 機制中的系統(tǒng)調(diào)用代理不能夠執(zhí)行進程位于用戶空間的代碼,如果在執(zhí)行多個系統(tǒng)調(diào)用函數(shù)之間必須執(zhí)行用戶空間代碼,那么這些系統(tǒng)調(diào)用函數(shù)將不能進行合并執(zhí)行。所以,當進程在一個循環(huán)中執(zhí)行多個系統(tǒng)調(diào)用時,multi-call 機制可能減少進程狀態(tài)轉(zhuǎn)換的次數(shù),但是不能實現(xiàn)使進程只經(jīng)過一次狀態(tài)變換就能執(zhí)行完成循環(huán)中的所有系統(tǒng)調(diào)用。實現(xiàn)內(nèi)核專門功能模塊方式,采用的方法是將用戶進程需要訪問內(nèi)核服務的功能實現(xiàn)為一個內(nèi)核模塊,每次用戶進程只需要調(diào)用內(nèi)核模塊提供的服務即可,去除了多次狀態(tài)轉(zhuǎn)換,提高了程序運行效率。但是此種方式,靈活度不高,只能滿足特定要求,很難具有通用性。二進制重寫技術(shù)[2]方式,采取的途徑是對內(nèi)核中運行函數(shù)代碼進行優(yōu)化處理,如將對內(nèi)核中函數(shù)的調(diào)用轉(zhuǎn)換為內(nèi)聯(lián)對應函數(shù)的代碼,去除了函數(shù)調(diào)用過程,減少了函數(shù)執(zhí)行時間。位于內(nèi)核中的用戶進程[3]方式,考慮了將用戶進程放入內(nèi)核中執(zhí)行,實現(xiàn)程序性能的提升等。

    本文介紹了通過內(nèi)核腳本執(zhí)行引擎提升用戶進程執(zhí)行系統(tǒng)調(diào)用的性能。下文具體安排如下,先介紹了分析了Linux 系統(tǒng)調(diào)用具體過程,其次再介紹了內(nèi)核腳本執(zhí)行引擎的設計及組成結(jié)構(gòu),最后分別通過內(nèi)核腳本執(zhí)行引擎,普通系統(tǒng)調(diào)用機制實現(xiàn)對不同大小文件拷貝,測試完成操作耗費的時間。通過對測試結(jié)果的對比分析,證明了在用戶進程需要頻繁訪問系統(tǒng)調(diào)用進行狀態(tài)切換時,通過內(nèi)核腳本執(zhí)行引擎實現(xiàn)系統(tǒng)調(diào)用過程,能夠顯著的提升應用程序的性能。

    1 系統(tǒng)調(diào)用過程

    在Linux 系統(tǒng)中,程序的運行空間分為用戶空間和內(nèi)核空間(用戶態(tài)和內(nèi)核態(tài))。在用戶空間和內(nèi)核空間運行的進程擁有不同運行級別,在邏輯上是相互隔離。用戶進程通常不允許訪問內(nèi)核,當用戶進程需要獲得一定的系統(tǒng)服務時候,就必須使用系統(tǒng)調(diào)用。系統(tǒng)調(diào)用規(guī)定了用戶進程進入內(nèi)核空間的位置,然后程序運行空間由用戶態(tài)進入內(nèi)核態(tài)完成相關(guān)處理,處理完成后再返回到用戶態(tài)。

    Linux 系統(tǒng)調(diào)用是作為一種異常類型實現(xiàn),用戶進程通過執(zhí)行特定的機器代碼指令來產(chǎn)生異常信號,然后自動將系統(tǒng)切換為內(nèi)核態(tài)。在x86 體系結(jié)構(gòu)中,內(nèi)核支持通過兩種方式實現(xiàn)系統(tǒng)調(diào)用,即執(zhí)行int 0x80 指令或者執(zhí)行sysenter 指令。系統(tǒng)調(diào)用完成后,再執(zhí)行iret 指令或sysexit 指令將系統(tǒng)從返回到用戶態(tài)。下面只介紹使用int 0x80 指令實現(xiàn)系統(tǒng)調(diào)用的具體過程,使用sysenter 指令情況以此類似。

    用戶進程執(zhí)行系統(tǒng)調(diào)用的其主要過程為:用戶進程序進行必要的寄存器參數(shù)設置后,執(zhí)行int 0x80 指令,系統(tǒng)硬件切換用戶堆棧到內(nèi)核堆棧,并將相關(guān)寄存器壓入到內(nèi)核堆棧中,然后執(zhí)行system_call 函數(shù),該函數(shù)保存寄存器參數(shù)值,并根據(jù)eax 寄存器值確定sys_call_table 表中對應的系統(tǒng)調(diào)用函數(shù),調(diào)用對應函數(shù)執(zhí)行,執(zhí)行完畢后,system_call 函數(shù)恢復用戶進程在用戶堆棧中保存的寄存器值,將當前進程從內(nèi)核態(tài)轉(zhuǎn)換到用戶態(tài),使用戶進程在返回到用戶空間后繼續(xù)執(zhí)行。

    系統(tǒng)調(diào)用的執(zhí)行過程中,需要對進程的用戶空間和內(nèi)核空間中的寄存器進行保存和恢復,即保護現(xiàn)場,恢復現(xiàn)場的操作。當用戶進程頻繁的訪問系統(tǒng)調(diào)用時,執(zhí)行現(xiàn)場的保護和恢復的操作將要耗費較多時間,所以通過減少用戶進程執(zhí)行系統(tǒng)調(diào)用時狀態(tài)轉(zhuǎn)換次數(shù),進而減少用戶進程不必要的狀態(tài)轉(zhuǎn)換時間,是提高用戶進程執(zhí)行系統(tǒng)服務性能的一種途徑。

    在用戶空間編寫的程序,使用的是位于用戶空間的庫函數(shù),由庫函數(shù)負責執(zhí)行具體的系統(tǒng)調(diào)用過程。對用戶空間不同的系統(tǒng)調(diào)用函數(shù),在內(nèi)核中都有對應得系統(tǒng)調(diào)用服務函數(shù),例如讀文件,寫文件,刪除文件等,因此將普通程序中對庫函數(shù)調(diào)用轉(zhuǎn)換成對內(nèi)核空間系統(tǒng)調(diào)用處理函數(shù)的調(diào)用,是可實現(xiàn)的。

    2 內(nèi)核腳本執(zhí)行引擎

    2.1 工作原理

    將內(nèi)核腳本執(zhí)行引擎實現(xiàn)為一個可裝載的內(nèi)核模塊[4],作為一個虛擬設備驅(qū)動掛載在Linux 系統(tǒng)設備文件目錄下,普通用戶可通過訪問對應路徑與之進行通信。內(nèi)核腳本執(zhí)行引擎是通過讀取用戶進程提供的腳本文件,進行編譯,鏈接內(nèi)核中函數(shù)并執(zhí)行,完成戶進程相應得請求內(nèi)核服務。

    內(nèi)核腳本執(zhí)行引擎工作流程為,用戶進程將普通腳本文件路徑提供給內(nèi)核腳本執(zhí)行引擎,內(nèi)核腳本執(zhí)行引擎裝載腳本文件進行編譯,同時將程序中訪問的用戶空間系統(tǒng)調(diào)用入口函數(shù)轉(zhuǎn)換為內(nèi)核系統(tǒng)調(diào)用服務函數(shù),然后進行鏈接,最后生成可執(zhí)行代碼,對可執(zhí)行代碼進行注冊,然后將注冊信息返回給用戶進程,用戶進程可憑借注冊信息向內(nèi)核腳本執(zhí)行引擎提出請求,內(nèi)核腳本執(zhí)行引擎依據(jù)注冊信息執(zhí)行相應代碼。如果在編譯注冊腳本文件過程中出現(xiàn)錯誤,內(nèi)核腳本執(zhí)行引擎將通知用戶進程服務注冊失敗,放棄此次操作。

    內(nèi)核腳本執(zhí)行引擎由系統(tǒng)調(diào)用注冊模塊,符號管理模塊,編譯模塊,鏈接模塊,執(zhí)行模塊組成。系統(tǒng)結(jié)構(gòu)圖如圖1 所示。

    2.2 系統(tǒng)調(diào)用服務注冊模塊

    用戶進程向系統(tǒng)調(diào)用服務模塊提供腳本文件路徑進行系統(tǒng)調(diào)用服務請求。系統(tǒng)調(diào)用服務模塊判斷用戶進程提供的腳本文件信息是否已注冊,如果未注冊,服務模塊將把腳本文件路徑交給編譯模塊,由編譯模塊讀取腳本文件,進行編譯生成執(zhí)行代碼,再由鏈接模塊負責內(nèi)核函數(shù)的鏈接,最后由執(zhí)行模塊進行執(zhí)行;如果用戶進程系統(tǒng)請求腳本文件已注冊,系統(tǒng)調(diào)用服務模塊將通知執(zhí)行模塊直接執(zhí)行對應的代碼塊。各模塊將處理的結(jié)果信息反饋給系統(tǒng)調(diào)用服務模塊,由系統(tǒng)調(diào)用服務模塊進行處理。

    2.3 編譯模塊

    編譯模塊實現(xiàn)了如下主要功能:詞法分析,語法分析,生成分析樹,語義分析,中間代碼生成,代碼優(yōu)化,非法寫內(nèi)存操作檢測,程序數(shù)據(jù)內(nèi)存分配,目標代碼生成。內(nèi)核腳本執(zhí)行引擎結(jié)構(gòu)圖如圖1 所示。

    詞法分析的過程通過構(gòu)造確定性有限狀態(tài)自動機[5],識別出的源文件中的字符,數(shù)字,關(guān)鍵字,變量,字符串,注釋等,形成標記,并鏈入標記鏈表中。標記鏈表是雙向鏈表,其中的每個元素包含了當前標記的具體信息,例如類型,值等。對識別出的變量標記,將在符號管理模塊中進行登記,變量包括了全局變量和當前函數(shù)中定義的局部變量。

    語法分析的實現(xiàn)是通過編譯模塊讀取文法定義文件,依據(jù)文法規(guī)則,采用LR 語法分析算法,獲得可能出現(xiàn)的分析狀態(tài)集合,構(gòu)造LR 分析表,包含了Action 表和Goto 表,采用下推自動機模型,實現(xiàn)在時間復雜度為O(N)的情況下,完成對標記鏈表分析。語法分析共包含四種操作,分別是移進,歸約,報錯,接受。移動操作,對應得是讀入標記鏈表中的下一個標記,壓入分析棧中;歸約操作,是將分析棧中涉及標記,依照規(guī)約操作中對應得產(chǎn)生式,合并成一個新的標記;報錯操作,則是停止分析,將錯誤信息返回給服務注冊模塊,由服務注冊模塊進行處理;接受操作,分析完成,此時分析結(jié)果將只存在一個程序塊標記或全局變量定義標記,標記鏈中的標記已分析完成。

    生成分析樹是對語法分析的結(jié)果標記進行遞歸下降分析構(gòu)造的過程。分析樹中的節(jié)點結(jié)構(gòu)中包括了一個左子節(jié)點,一個右子節(jié)點以任意數(shù)目的伙伴節(jié)點等。節(jié)點類型包括了函數(shù)體,語句塊,語句,表達式,變量,關(guān)鍵字等。不同類型的節(jié)點擁有子節(jié)點的情況各不相同。單個變量是葉子節(jié)點,不具有子節(jié)點和伙伴節(jié)點。一維運算表達式只擁有左子節(jié)點。二維算數(shù)表達式擁有左子節(jié)點和右子節(jié)點。循環(huán)語句結(jié)構(gòu)則擁有左子節(jié)點,右子節(jié)點和擁有多個伙伴節(jié)點等。

    中間代碼生成和語義分析同時進行。中間代碼生成是對分析樹進行遍歷,產(chǎn)生偽代碼指令鏈表的過程。分析樹中不同類型的節(jié)點,都有對應的偽指令生成模塊用于偽指令生成,在遍歷分析樹的過程中,只要調(diào)用節(jié)點對應偽指令生成模塊實現(xiàn)偽指令生成。與此同時進行語義分析,依據(jù)節(jié)點的類型分析當前節(jié)點的結(jié)構(gòu),執(zhí)行的操作是否有效。例如分析表達式是否有效,即按照當前表達式中變量的類型是否合法,表達式的操作是否合法,進而判斷表達式是否有效。

    代碼優(yōu)化,目前主要是實現(xiàn)了對無用偽指令代碼的刪除。中間代碼的產(chǎn)生是按照節(jié)點對應的生成模塊產(chǎn)生的,生成的偽指令代碼存在無用代碼,對可能是無用指令代碼的部分設定范圍標識,如果經(jīng)過判斷確定該范圍內(nèi)偽指令代碼不被使用,則將此范圍的偽指令代碼可從偽代碼指令鏈中刪除。

    非法寫內(nèi)存操作檢測,實現(xiàn)的功能是檢測程序中動態(tài)的訪問內(nèi)存地址并進行寫操作的指令,判斷其所訪問的內(nèi)存地址是否合法。進程在內(nèi)核中執(zhí)行,需要保證進程不能夠非法修改內(nèi)核中其他重要的數(shù)據(jù)結(jié)構(gòu),進程中的執(zhí)行函數(shù)只能修改當前進程定義的變量包括了全局變量,局部變量,函數(shù)傳遞參數(shù)等。編譯模塊為當前執(zhí)行進程分配了固定的內(nèi)存區(qū)域用于變量的存儲,進程能夠進行寫內(nèi)存操作的目標地址也只能在此區(qū)域內(nèi)。對程序中動態(tài)寫內(nèi)存的指令,編譯模塊在編譯時,在該指令前插入了用于判斷目標內(nèi)存地址是否在當前程序分配的固定內(nèi)存區(qū)域內(nèi)的檢測指令。在程序運行時,檢測指令將判斷寫內(nèi)存操作所訪問的內(nèi)存地址是否處于當前程序分配的內(nèi)存區(qū)域內(nèi),如果所訪問的內(nèi)存地址不屬于分配的內(nèi)存區(qū)域,說明程序執(zhí)行的寫內(nèi)存操作是非法的,檢測指令將會使程序停止運行,并報告程序?qū)憙?nèi)存操作非法錯誤。對于固定內(nèi)存地址訪問,編譯模塊不添加監(jiān)視指令,因為訪問內(nèi)存地址已知,并且位于程序分配的內(nèi)存區(qū)域內(nèi)。

    程序數(shù)據(jù)內(nèi)存分配。當前采取的方式是編譯模塊為用戶進程預分配了固定大小內(nèi)存區(qū)域,用于存儲當前執(zhí)行函數(shù)的局部變量及傳遞的參數(shù)。在函數(shù)調(diào)用過程中,編譯模塊通過堆棧傳遞參數(shù),同時編譯模塊在當前函數(shù)分配的內(nèi)存區(qū)域內(nèi),也分配了對應參數(shù)存儲的內(nèi)存,并在函數(shù)指令開始部分插入?yún)?shù)移動指令,負責將堆棧上的參數(shù)移動到程序分配的內(nèi)存區(qū)內(nèi)。用戶定義的函數(shù)只訪問和修改處于函數(shù)內(nèi)存分配區(qū)域中的參數(shù)。并通過非法寫內(nèi)存操作檢測,防止用戶進程修改調(diào)用堆棧中的操作。目前只針對用戶編寫的腳本文件代碼進行分析,未考慮調(diào)用庫函數(shù)等因素。目前暫不支持函數(shù)遞歸調(diào)用。

    目標代碼生成,是將偽指令代碼直接翻譯成機器指令的過程,目前只支持Intel x86 指令集。通過遍歷偽指令代碼鏈即實現(xiàn)此過程,同時對函數(shù)調(diào)用指令進行記錄,用于鏈接模塊進行內(nèi)核函數(shù)及用戶自定義函數(shù)的鏈接。

    2.4 鏈接模塊

    鏈接模塊通過獲取編譯模塊產(chǎn)生的函數(shù)調(diào)用記錄,包括了用戶自定義函數(shù)和系統(tǒng)調(diào)用函數(shù),對腳本文件中系統(tǒng)調(diào)用函數(shù)的調(diào)用,鏈接模塊能夠自動匹配腳本中使用的系統(tǒng)調(diào)用函數(shù)和相應的內(nèi)核函數(shù),通過查找獲得相應內(nèi)核函數(shù)地址,然后更新目標代碼中函數(shù)調(diào)用指令中函數(shù)偏移量值,實現(xiàn)程序?qū)?nèi)核系統(tǒng)調(diào)用函數(shù)的引用。同時,內(nèi)核中存在部分函數(shù)不能夠通過此方式進行直接鏈接,鏈接模塊實現(xiàn)了為這樣的函數(shù)實現(xiàn)了相應的適配函數(shù),對這類內(nèi)核函數(shù),鏈接模塊將鏈接相應的適配函數(shù),由適配函數(shù)實現(xiàn)對內(nèi)核系統(tǒng)調(diào)用服務函數(shù)的調(diào)用。

    2.5 執(zhí)行模塊

    依據(jù)調(diào)用服務注冊傳遞的代碼塊注冊信息,創(chuàng)建一個內(nèi)核任務,執(zhí)行對應的代碼塊,并將執(zhí)行結(jié)果返回給系統(tǒng)調(diào)用服務注冊模塊。

    2.6 符號管理模塊

    記錄了編譯模塊和鏈接模塊中使用的符號信息和占用內(nèi)存信息。涉及的符號包括了函數(shù)符號以及結(jié)構(gòu)體,字符串,數(shù)值等變量符號。函數(shù)符號記錄了函數(shù)起始地址,函數(shù)塊的大小等信息;變量符號記錄了變量存儲的內(nèi)存地址,變量的類型,占用內(nèi)存大小等信息。

    3 實驗

    測試環(huán)境中Linux 操作系統(tǒng)為Gentoo,Linux 內(nèi)核版本為2.6.30,內(nèi)存為512M,CPU 為1.50GHZ,gcc 版本為4.1.2。分別采用內(nèi)核腳本執(zhí)行引擎編譯腳本執(zhí)行以及普通的文件拷貝程序,實現(xiàn)對不同大小文件的拷貝操作,使用gettimeofday 函數(shù)獲取程序的執(zhí)行時間。用于文件拷貝的緩沖大小為4096 字節(jié)。測試中實現(xiàn)文件拷貝源程序代碼如圖2。用戶程序通過gcc 編譯生成可執(zhí)行程序,生成代碼未使用優(yōu)化選項。使用腳本執(zhí)行引擎方式,既可在內(nèi)核中將此源程序?qū)崿F(xiàn)為一個拷貝文件的函數(shù),然后在腳本文件中引用此函數(shù)實現(xiàn)文件的拷貝,也可將此源程序直接提供給腳本執(zhí)行引擎,由腳本執(zhí)行引擎編譯生成執(zhí)行代碼,執(zhí)行完成文件的拷貝。為了測量內(nèi)核中執(zhí)行拷貝操作所能達到性能的最大提升,測試中采取了前一種方式。實際測試過程中,每類數(shù)據(jù)共測試100 次,取其平均值,測試結(jié)果如圖3。采用腳本執(zhí)行引擎實現(xiàn)文件拷貝獲得的性能提升如圖4。

    通過圖4 可看出,使用內(nèi)核腳本執(zhí)行引擎實現(xiàn)文件拷貝,相對于普通用戶程序執(zhí)行文件拷貝,在性能上有很大提升。

    圖1:內(nèi)核腳本執(zhí)行引擎結(jié)構(gòu)圖

    圖2:文件拷貝源程序

    圖3:文件拷貝時間折線圖

    圖4:文件拷貝優(yōu)化比率

    4 小結(jié)

    本文介紹了利用內(nèi)核腳本執(zhí)行引擎編譯執(zhí)行用戶進程提供的腳本文件,完成用戶進程執(zhí)行系統(tǒng)調(diào)用的操作,減少了用戶進程進行狀態(tài)轉(zhuǎn)換的次數(shù),提高用戶進程執(zhí)行系統(tǒng)調(diào)用的性能,為用戶進程實現(xiàn)優(yōu)化系統(tǒng)調(diào)用過程提供了較為簡便的途徑。目前已有許多關(guān)于提升Linux 運行性能的研究工作正在持續(xù)展開,例如提升Realtime Linux 系統(tǒng)性能[6][7],針對Arm 芯片上系統(tǒng)的性能優(yōu)化[8][9][10],這些改善系統(tǒng)性能的工作應用于當前的工業(yè)控制領域具有一定的意義。

    猜你喜歡
    腳本內(nèi)核調(diào)用
    酒駕
    萬物皆可IP的時代,我們當夯實的IP內(nèi)核是什么?
    強化『高新』內(nèi)核 打造農(nóng)業(yè)『硅谷』
    安奇奇與小cool 龍(第二回)
    核電項目物項調(diào)用管理的應用研究
    基于嵌入式Linux內(nèi)核的自恢復設計
    Linux內(nèi)核mmap保護機制研究
    LabWindows/CVI下基于ActiveX技術(shù)的Excel調(diào)用
    數(shù)據(jù)庫系統(tǒng)shell腳本應用
    電子測試(2018年14期)2018-09-26 06:04:24
    快樂假期
    中學生(2017年19期)2017-09-03 10:39:07
    内丘县| 尼木县| 探索| 柞水县| 通州区| 上杭县| 兴仁县| 泸州市| 永和县| 新宁县| 信丰县| 新竹市| 东乌| 鄂托克前旗| 新竹县| 朝阳县| 郯城县| 响水县| 洛川县| 承德县| 龙海市| 固阳县| 绥德县| 怀集县| 天水市| 木兰县| 荣成市| 临洮县| 陇西县| 建水县| 平昌县| 娱乐| 连平县| 池州市| 乐安县| 彭山县| 昌黎县| 建阳市| 抚远县| 平乐县| 南通市|