基于Linux 的嵌入式瀏覽器的研究
隨著信息技術(shù)與網(wǎng)絡(luò)技術(shù)的快速發(fā)展, 以及人們?nèi)粘I顚W(wǎng)絡(luò)信息的需求的不斷增加。掌上電腦、上網(wǎng)本、手機(jī)、導(dǎo)航儀器、智能電視、智能家電等對嵌入式系統(tǒng)提出了更多更高的要求。在嵌入式系統(tǒng)中利用嵌入式瀏覽器獲取網(wǎng)絡(luò)信息是必不可少的, 因此嵌入式瀏覽器技術(shù)成為現(xiàn)如今的技術(shù)熱點(diǎn)之一。而且Linux 操作系統(tǒng)完全開源, 可以降低產(chǎn)品開發(fā)成本, 因此對基于Linux 操作系統(tǒng)的嵌入式瀏覽器開發(fā)技術(shù)的研究有著重要意義。
1 嵌入式瀏覽器的結(jié)構(gòu)
根據(jù)嵌入式瀏覽器的特點(diǎn), 分析嵌入式瀏覽器的各個部分功能。下面介紹嵌入式瀏覽器的主要功能:
(1) 詞法分析, 主要是對HTML 語言進(jìn)行詞法分析, 并且要求HTML 詞法分析可以兼容XML 等其他標(biāo)簽語言,達(dá)到只需更換語言的元素名稱就可以進(jìn)行詞法分析的效果;(2) 語法分析與布局, 在非嵌入式瀏覽器中語法分析是獨(dú)立的一個模塊, 但是在嵌入式瀏覽器中不作為一個獨(dú)立模塊, 簡化系統(tǒng)結(jié)構(gòu), 即實(shí)現(xiàn)語法分析與布局同步化, 節(jié)省了語法分析數(shù)據(jù)存儲的內(nèi)存空間; (3) 嵌入式瀏覽器的用戶界面, 設(shè)計高效快捷的用戶界面是應(yīng)用軟件的重要部分;(4) 嵌入式瀏覽器JavaScript 支持,JavaScript 在瀏覽器里主要是用于操縱界面元素并與瀏覽器內(nèi)部命令進(jìn)行結(jié)合;(5)I/O 端, 主要是通過HTTP 協(xié)議和文本系統(tǒng)來讀取頁面信息;(6) 控制機(jī)制, 負(fù)責(zé)命令響應(yīng)和消息處理。嵌入式瀏覽器功能結(jié)構(gòu)如圖1 所示。
圖1 嵌入式瀏覽器功能結(jié)構(gòu)圖
2 HTML 詞法分析
2.1 組成及功能
HTML 詞法分析是嵌入式瀏覽器開發(fā)的基礎(chǔ), 是整個嵌入式瀏覽器整體設(shè)計的最前端部分,HTML 詞法分析的數(shù)據(jù)結(jié)構(gòu)是語法分析與布局的重要依據(jù)。HTML詞法分析的效率、準(zhǔn)確率以及容錯率的高低在一定程度上決定了整個嵌入式瀏覽器的工作效率。下面對HTML詞法分析的組成和功能進(jìn)行解析。
HTML 詞法分析的功能主要是負(fù)責(zé)接收從I/O 端讀取到的HTML 代碼并進(jìn)行詞法分析, 提取網(wǎng)頁中HTML代碼中的各元素信息, 按照定義的數(shù)據(jù)結(jié)構(gòu)保存元素的屬性和名稱等, 實(shí)現(xiàn)數(shù)據(jù)的結(jié)構(gòu)化。
根據(jù)HTML 詞法分析的功能可以解析為幾個組成部分:(1) 初始化。完成對數(shù)據(jù)結(jié)構(gòu)的初始化, 主要是分配內(nèi)存, 變量賦初值; (2) 主體的數(shù)據(jù)流分析, 逐字符地進(jìn)行判斷, 確定數(shù)據(jù)的歸屬類型; (3) 元素的分析, 提取元素的名稱、屬性和值域; (4) 釋放, 主要是對數(shù)據(jù)內(nèi)存空間的釋放。
2.2 算法
根據(jù)HTML 詞法分析的功能以及組成部分, 可以很清晰地得到一個簡單的算法。其算法過程具體如下:
(1)從I/O 端讀取的字符串流中,順序讀取一個字符;(2) 如果遇到< , 表示將遇到元素, 處理該元素( 使用元素處理函數(shù)來處理該元素) , 元素處理結(jié)束后, 指針指向該元素的尾部;(3) 如果遇到空格或回車, 則跳過;(4) 如果遇到>, 則跳過(因?yàn)椴豢赡艽嬖?lt;>這種不包含任何元素的情況, 只是為了增強(qiáng)程序的容錯性);(5) 如果遇到的不是上述幾種情況, 則遇到的是文字( 使用文字處理函數(shù)來處理該文字) , 文字處理結(jié)束后,指針指向下一個元素的首部;(6) 循環(huán)(1)~(5 ) 步驟, 直到I/O 端讀取的字符串流全部分析完。
根據(jù)上述詞法分析算法過程可以得到相應(yīng)的流程圖, 如圖2 所示。
圖2 詞法分析算法流程圖 2.3 詞法分析的設(shè)計 根據(jù)上述提出的詞法分析的算法, 通過掃描I/O 端讀取的字符串, 來檢測字符是否為標(biāo)簽元素、提取標(biāo)簽元素屬性等。設(shè)計詞法分析的基礎(chǔ)要定義數(shù)據(jù)結(jié)構(gòu), 為詞法分析算法的實(shí)現(xiàn)提供基礎(chǔ)。根據(jù)功能需要設(shè)計基本的數(shù)據(jù)結(jié)構(gòu), 定義如下: char token[]; // 標(biāo)簽元素表 char * tokenPointer; //指向標(biāo)簽元素表的指針 char chText[]; // 字符表 char *chPointer; // 字符表指針 char text[]; // 字符串表 char *textPointer; // 字符串表指針 char textRead[]; //存放待識別的源程序字符串 char *textReadPointer; //讀取字符串指針 char ch; //存放最讀取的源程序字符 char STrToken[]; //存放構(gòu)成單詞符號的字符串 bool flag=false; //是否掃描過一次 3 瀏覽器JavaScript 支持 3.1 JavaScript 簡介 JavaScript 是一種基于對象和事件驅(qū)動并具有相對安全性的客戶端腳本語言。它的一個重要功能就是面向?qū)ο蟮墓δ埽?通過基于對象的程序設(shè)計, 可以用更直觀、模塊化和可重復(fù)使用的方式進(jìn)行程序開發(fā)。一組包含數(shù)據(jù)的屬性和對屬性中包含數(shù)據(jù)進(jìn)行操作的方法, 稱為對象。用戶與網(wǎng)頁交互時產(chǎn)生的操作, 稱為事件。事件可以由用戶引發(fā), 也可能是頁面發(fā)生改變, 甚至還有看不見的事件( 如Ajax 的交互進(jìn)度改變) 。絕大部分事件都由用戶的動作所引發(fā), 例如用戶按鼠標(biāo)的按鍵, 就產(chǎn)生click 事件, 若鼠標(biāo)的指針在鏈接上移動, 就產(chǎn)生MouseOver 事件等。在JavaScript 中, 事件與事件處理程序配套使用。而對事件的處理用addEventListener() 函數(shù), 它有3 個參數(shù): 事件、引發(fā)的函數(shù)以及是否使用事件捕捉。 為了保障安全性, 將第三個參數(shù)始終設(shè)置為false。 JavaScript 具有幾個特性: 能使網(wǎng)頁增加互動性; 能使有規(guī)律地重復(fù)的HTML 源代碼簡化, 減少下載時間;能及時響應(yīng)用戶的操作, 對提交表單做即時的檢查, 無需浪費(fèi)額外的驗(yàn)證時間。 3.2 JavaScript 引擎 JavaScript 引擎一般作為共享庫使用, 應(yīng)用程序調(diào)用引擎提供的API 函數(shù)。引擎API 函數(shù)大致分為以下幾種: 數(shù)據(jù)類型操作、RunTime 控制、類與對象的創(chuàng)建和維護(hù)、函數(shù)與腳本執(zhí)行、字符串操作、錯誤處理、安全控制、Debug 支持。一般情況下, 在應(yīng)用程序中只需使用某幾類函數(shù)。例如, 在進(jìn)行JavaScript 調(diào)用之前必須調(diào)用JS_NewRuntime 函數(shù)來創(chuàng)建并初始化JavaScript 引擎。有些類型的函數(shù)(像安全控制類)提供可選擇的特征。 JavaScript 引擎是系統(tǒng)上的一個共享資源。通過將引擎API 調(diào)用嵌入到應(yīng)用程序中, 可以請求JavaScript 引擎進(jìn)行操作。引擎處理請求, 并將結(jié)果或狀態(tài)信息返回給應(yīng)用程序。例如, 假定使用JavaScript 引擎自動化應(yīng)用程序, 腳本應(yīng)用程序鑒別用戶并設(shè)置權(quán)限。首先, 應(yīng)用程序創(chuàng)建JavaScript 對象, 該對象描述用戶信息, 包括姓名、ID、權(quán)限和可用的函數(shù)列表。在這種情況下, 應(yīng)用程序首先調(diào)用JS_NewObject 創(chuàng)建對象。當(dāng)JavaScript 引擎創(chuàng)建對象后, 返回一個指針給應(yīng)用程序。應(yīng)用程序再調(diào)用JavaScript 引擎執(zhí)行腳本。在創(chuàng)建用戶對象后, 應(yīng)用程序即刻傳遞腳本給JS_EvaluateScript 以便編譯和運(yùn)行。腳本獲許取得并校驗(yàn)用戶信息, 然后建立用戶存取的權(quán)利。 JavaScript 引擎收到初始化請求后,給JavaScript Run-Time 分配內(nèi)存, 應(yīng)用程序使用的變量、對象和上下文都保存在RunTime 中。一個上下文是腳本的執(zhí)行狀態(tài)(JavaScript 引擎使用的) 。每個同時存在的腳本或線程都必須有自己的上下文。單個的JavaScript RunTime 可以包含多個上下文、對象和變量。幾乎所有的JavaScript 引擎調(diào)用都需要一個上下文變量, 應(yīng)用程序在創(chuàng)建RunTime后, 首先應(yīng)調(diào)用至少一次JS_NewCONtext 來創(chuàng)建一個上下文。上下文的實(shí)際數(shù)量依賴于程序中同時使用的腳本數(shù)。程序中每個同時存在的腳本都需要一個上下文。另一方面, 如果某個時刻只有一個腳本編譯和運(yùn)行, 則只需一個上下文給每個腳本重復(fù)使用即可。 3.3 JavaScript 與瀏覽器結(jié)合 3.3.1 直接加入方式 絕大部分含有JavaScript 代碼的網(wǎng)頁都采用直接加入的方式。 <script type="test/javascript"> document.write("This is Javascript! "); </script> 其中,<script> </script> 是JavaScript 的標(biāo)簽。<scripttype = "test/javascript" > 用來提示瀏覽器該程序采用JavaScript 語言編寫, 需要調(diào)動相應(yīng)的解釋程序進(jìn)行解釋。 除此之外, 還有一個更高版本的嵌入腳本, 使用HTML 中的CDATA 語法, 就是把CDATA 中的文本全部當(dāng)作純文本處理, 當(dāng)遇到CDATA 時結(jié)束。 <script language="javascript" type="test/javascript"> <! CDATA[[> <! ]]> </script> 3.3.2 引用方式 如果已經(jīng)存在一個JavaScript 源文件(以js 為擴(kuò)展名),則可以采用引用的方式提高程序代碼的利用率。其基本格式如下: <script src="url" type="test/javascript"> </script> 其中url 就是程序文件的地址。 同樣地, 這樣的JavaScript 程序語句可以放在HTML文檔頭部或主體的任何部分。如果要實(shí)現(xiàn)直接加入JavaScript 程序代碼, 可以首先創(chuàng)建一個JavaScript 源代碼文件“javascript.js ” , 其代碼為document.write ("This isJavascript! ") 。在網(wǎng)頁中調(diào)用程序的方法, 如: <script src="javascript.js" type="test/javascript"> </script> 也可以同時在導(dǎo)入文件時指定JavaScript 的版本,如: <script src = "javascript.js" type = "test/javascript; version =2.0"> </script> 本文對Linux 操作系統(tǒng)的嵌入式瀏覽器進(jìn)行了研究與分析。分析了嵌入式瀏覽器的結(jié)構(gòu), 并對嵌入式瀏覽器的各部分功能進(jìn)行闡述, 其中包括詞法分析、語法分析與布局、瀏覽器JavaScript 支持、I/O 端等部分。其中,在嵌入式瀏覽器的研究過程中, 詞法分析的算法是開發(fā)技術(shù)的核心。在后續(xù)研究工作中, 可以對詞法分析算法做進(jìn)一步的研究, 提高詞法分析的效率, 完善嵌入式瀏覽器功能實(shí)現(xiàn)的效果。