基于ARM-Linux的SQLite嵌入式數(shù)據(jù)庫的研究
關(guān)鍵詞:嵌入式數(shù)據(jù)庫;SQLite;ARM-Linux平臺;交叉編譯
Abstract :SQLite is an open source embedded SQL database engine. At first,descripe some general databases’ technology in this paper, and then Internal architecture and developing method of SQLite are analyzed. The application developing ,cross compiling and porting in ARM-Linux platform are also introduced and a detailed example is given for presentation.
Keywords :Embedded Databese; SQLite; ARM-Linux platform; cross compiling
引言
隨著嵌入式系統(tǒng)的廣泛應(yīng)用和用戶對數(shù)據(jù)處理和管理需求的不斷提高,各種智能設(shè)備和數(shù)據(jù)庫技術(shù)的緊密結(jié)合已經(jīng)得到了各方面的重視。不久的將來嵌入式數(shù)據(jù)庫將無處不在??v觀目前國際、國內(nèi)嵌入式數(shù)據(jù)庫的應(yīng)用情況,目前基于嵌入式數(shù)據(jù)庫應(yīng)用的市場已經(jīng)進入加速發(fā)展的階段。
1 嵌入式數(shù)據(jù)庫
1.1 嵌入式數(shù)據(jù)庫的設(shè)計
嵌入式數(shù)據(jù)庫系統(tǒng)是指支持某種特定計算模式或移動計算的數(shù)據(jù)庫管理系統(tǒng),它通常與操作系統(tǒng)和具體應(yīng)用集成在一起,運行在智能型嵌入式設(shè)備或移動設(shè)備上。嵌入式數(shù)據(jù)庫的使用是采用程序驅(qū)動,即由程序調(diào)用相應(yīng)的API來實現(xiàn)數(shù)據(jù)的存取。具有體積小巧、快速高效、穩(wěn)定可靠、可移植性等特點,非常適用于嵌入式環(huán)境下的數(shù)據(jù)管理.。
嵌入式數(shù)據(jù)庫的主要設(shè)計思想如下圖1所示,在向上層應(yīng)用提供標準的數(shù)據(jù)庫接口的同時,擺脫傳統(tǒng)數(shù)據(jù)庫僅僅由軟件驅(qū)動的束縛,根據(jù)嵌入式系統(tǒng)的實際情況用SOC技術(shù)同時實現(xiàn)硬件驅(qū)動。軟件部分按SQL92標準實現(xiàn)SQL語句的解析,實現(xiàn)事務(wù)管理功能、數(shù)據(jù)同步機制、數(shù)據(jù)的備份和恢復(fù),軟件部分不關(guān)心數(shù)據(jù)的實際存儲,用標準C實現(xiàn),能同任何嵌入式操作系統(tǒng)內(nèi)核一同編譯,能支持各嵌入式操作系統(tǒng)的安裝格式,由數(shù)據(jù)庫硬件驅(qū)動專用芯片實現(xiàn)對實際數(shù)據(jù)的訪問功能(存儲器讀寫,I/O通訊,異構(gòu)數(shù)據(jù)庫接駁)。
圖1 嵌入式數(shù)據(jù)庫驅(qū)動結(jié)構(gòu)圖
1.2. 嵌入式數(shù)據(jù)庫SQLite
SQLite 是D. Richard Hipp 在2000年開發(fā)的一個小型嵌入式數(shù)據(jù)庫。他是完全獨立的,不具有外部依賴性,可以較為方便地應(yīng)用于嵌入式系統(tǒng)中。其源代碼完全開放,可以免費用于任何用途,包括商業(yè)目的。SQLite 雖然是個極端輕量級的關(guān)系數(shù)據(jù)庫,卻保留了數(shù)據(jù)庫的大部分特征,他提供了對SQL92 標準的大多數(shù)支持:支持多表和索引、事務(wù)、視圖、觸發(fā)和一系列的用戶接口及驅(qū)動。其主要特征如下::
(1) 支持原子的、一致的、獨立的和持久的(ACID) 事務(wù)特性,即使系統(tǒng)崩潰和掉電。
(2) 零配置(Zero2configuration),無需安裝和管理。
(3) 一個完整的數(shù)據(jù)庫存儲在單一磁盤文件中。
(4) 數(shù)據(jù)庫文件可以在不同字節(jié)順序的機器間自由共享。
(5) 支持數(shù)據(jù)庫大小至2 TB。
(6) 字符串和二進制大對象(BLOBs) 的大小僅被有效內(nèi)存限制。
(7) 源碼體積小,編譯后低于250 kB。
(8) 大部分的操作比關(guān)系型數(shù)據(jù)庫引擎要快。
(9) 簡單易用的API。
SQLite 由于小、快、簡單、可靠,而且作者完全放棄版權(quán),從他一發(fā)布出來,便深受歡迎。對于嵌人式環(huán)境,管理、執(zhí)行、維護的簡單化比企業(yè)數(shù)據(jù)庫引擎提供的許多復(fù)雜應(yīng)用更重要,因此SQLite 數(shù)據(jù)庫是一個很好的選擇。
2 SQLite 內(nèi)部結(jié)構(gòu)及開發(fā)技術(shù)
2. 1 SQLite 內(nèi)部結(jié)構(gòu)
SQLite 采用模塊化的設(shè)計,主要由4個部分組成:內(nèi)核(Core)、SQL編譯器( SQL Compiler)、后端(Backend)以及附件(Accessories)。內(nèi)部結(jié)構(gòu)如圖2所示。
圖2 SQLite 的內(nèi)部結(jié)構(gòu)
SQLite 的接口是一些已經(jīng)編寫好的C庫,即使使用不同語言的API,在底層仍然使用C 庫執(zhí)行。SQL語句通過接口進入到高效的SQL編譯器,由標記處理器( tokeni2zer)分解成檸檬分析器(par ser) 可以識別的各個標志符,然后由分析器重新組合標志符并調(diào)用代碼生成器(code generator) 生成虛擬機器碼,交由虛擬機( virtual machine)去執(zhí)行,最終完成SQL 語句指定的任務(wù)。虛擬機是SQLite 內(nèi)部結(jié)構(gòu)的核心,不僅完成與數(shù)據(jù)操作相關(guān)的全部操作,而且還是客戶和存儲之間信息進行交換的中間單元。數(shù)據(jù)庫按照B樹(B2t ree) 的形式存儲在磁盤上,通過可調(diào)整的頁面緩沖(pager) 獲得對數(shù)據(jù)的快速查找和存儲。為了方便移植,SQLite 使用一個抽象層接口(OS in2terface) 與不同操作系統(tǒng)進行對接。
2. 2 SQLite 開發(fā)技術(shù)
SQLite 本身提供了C 語言的API 接口,使得對數(shù)據(jù)庫的操作十分簡單,主要是對3個API 函數(shù)的調(diào)用。
(1) 打開數(shù)據(jù)庫
int sqlite3 open (
const char 3 filename , / 3 數(shù)據(jù)庫文件名(U TF28) 3 /
sqlite3 3 3 ppDb / 3 輸出SQLite 數(shù)據(jù)庫句柄3 /
) ;
(2) 執(zhí)行SQL
int sqlite3 exec (
sqlite3 3 , / 3 已經(jīng)打開的數(shù)據(jù)庫句柄3 /
const char 3 sql , / 3 要執(zhí)行的SQL 語句3 /
sqlite callback , / 3 回調(diào)函數(shù)3 /
void 3 , / 3 回調(diào)函數(shù)的第一個參數(shù)3 /
char 3 3 errmsg / 3 錯誤信息返回3 /
) ;
(3) 關(guān)閉數(shù)據(jù)庫
int sqlite3 close ( sqlite3 3 ) ; / 3 參數(shù)就是打開時的結(jié)構(gòu)體,即數(shù)據(jù)庫句柄3 /
其中,sglite3 exec ( ) 函數(shù)的第二個參數(shù)用來處理一條或多條SQL 語句,語句間必須用“;”號隔開。如果是查詢(SEL ECT) 語句,查詢結(jié)果的每一條記錄都必須調(diào)用第三個參數(shù)的Callback 函數(shù),第四個參數(shù)則為Callback 函數(shù)的第一個參數(shù)指針。如果不是查詢語句,第三、四個參數(shù)為NULL。所有SQL 執(zhí)行完畢后返回0,否則返回錯誤代碼,可通過第五個參數(shù)值來查看詳細錯誤信息。
3 SQLite 在ARM-Linux 平臺上的實現(xiàn)
SQLite 嵌入式數(shù)據(jù)庫提供了以源碼發(fā)布的方式,要在眾多的硬件平臺進行移植,可以根據(jù)不同平臺對源碼進行交叉編譯來實現(xiàn)。編譯主要有以下幾個步驟:
① 到http :/ / www. sqlite. org/ 的cvs中下載最新的源代碼包,解壓并根據(jù)需要進行適當?shù)男薷暮髮⑸蓅qlite目錄,另外新建并轉(zhuǎn)到一個與sqlite目錄平行的同級目錄,如make目錄。
②用“echo $PATH”命令查看PATH中是否已經(jīng)包含交叉編譯工具arm linux gcc。
③為了在ARM Linux下能正常運行sqlite,需要對sqlite/ src/ sqliteInt . h作一定的修改,以確保bt ree (B 樹)有正確的變量大小,如“pt r”和“char 3 ”。不同體系結(jié)構(gòu)的Linux,如x86 和ARM,會有些差別。對于ARM2Linux可以找到如下部分:
# ifndef IN TPTR_ TYPE
# if SQL ITE_PTR_SZ = = 4
# define IN TPTR_ TYPE int
# else
# define IN TPTR_ TYPE long long
# endif
在上面的代碼前加上一句
# define SQL ITE_PTR_SZ 4
這樣后面的“typedef INTPTR_ TYPE pt r ;”就是定義的“int”類型,而不是“l(fā)ong long”。
④準備使用configure進行一些配置。請在sqlite目錄下的configure中找到如下4處,并將他們注釋掉,這樣可以讓configure不去檢查你的交叉編譯環(huán)境。
⑤修改Makefile文件。將代碼行BCC = arm linux gcc g O2 改成BCC = gcc g O2 。另外,一般是以靜態(tài)鏈接的形式將sqlite 放到ARM Linux 的硬件板上運行的,所以繼續(xù)修改Makefile ,找到標記為sqlite :的代碼段,將其中的libsqlite. la 改成. libs/ libsqlite. a 。做完上述修改,用make 生成sqlite 、libsqlite. a 、libsqlite. so 。為了減小執(zhí)行文件大小可以用st rip 處理,去掉其中的調(diào)試信息。
⑥在ARM 板上運行sqlite。將sqlite 拷貝到ARM板上,方法很多,需要根據(jù)具體的情況來選擇。如ftp 、cm2 dftp 、wget 等。將sqlite下載到ARM 板的/ tmp 目錄,因為此目錄是可寫的。修改權(quán)限并運行:
chmod + wx sqlite
. / sqlite test . sqlite
會出現(xiàn)
sqlite >
如果一切正常,現(xiàn)在sqlite已經(jīng)在ARM Linux下跑了起來,然后就可以基于此進行進一步的應(yīng)用開發(fā)了。
4 SQLite 在ARM- Linux 系統(tǒng)中應(yīng)用實例
在基于Linux的媒體網(wǎng)絡(luò)附屬存儲(media network attached storage,Media NAS)系統(tǒng)中,選用SQLite數(shù)據(jù)庫作為NAS系統(tǒng)中媒體數(shù)據(jù)的存儲數(shù)據(jù)庫,使得數(shù)字媒體播放設(shè)備通過UPnP ( universal plug-and-play)協(xié)議對NAS上的媒體文件進行播放。該系統(tǒng)中用戶瀏覽媒體文件的流程如下::
(1)當用戶瀏覽NAS系統(tǒng)中的媒體文件時,執(zhí)行DatabaseOpen數(shù)據(jù)庫打開操作。
(2)接著查找當前的SQLite數(shù)據(jù)庫表,得到媒體文件的路徑,通過DatabaseExecute執(zhí)行SQL 查詢語句得到路徑。
(3)通過媒體文件的路徑打開媒體文件,把媒體文件,通過UPnP網(wǎng)絡(luò)發(fā)送出去。SQLite的特點決定了它與應(yīng)用結(jié)合時的便捷性。作為數(shù)據(jù)的存儲介質(zhì),SQLite文件被保存為一個普通的磁盤二進制文件,它無需一個服務(wù)器進程來提供服務(wù),對SQLite數(shù)據(jù)文件的直接操作即可完成想要做的工作。結(jié)合應(yīng)用需求,在應(yīng)用層編寫了一組對SQLite的API調(diào)用操作的簡單封裝,部分封裝函數(shù)如下::
DatabaseOpen ;調(diào)用SQLite_open打開數(shù)據(jù)庫文件
DatabaseClose ;調(diào)用SQLite_close關(guān)閉數(shù)據(jù)庫
DatabaseExecute ;執(zhí)行SQL命令
應(yīng)用層的部分封裝函數(shù)的實現(xiàn)代碼如下::
int DatabaseOpen ( struct DBObj3 db, const char3 dbName)
{
char3 pzErrMsg = NULL;
structDB Info3 pDB info; / /數(shù)據(jù)庫文件指針
if (NULL = = dbName) return 1;
pDBinfo = ( struct DB Info3 ) db - > priv;
pDBinfo - > stConnect = ( struct sqlite3 ) sqlite_open ( dbName, 0777, &pzErrMsg) ;
if ( NULL = = pDB info - > stConnect )
{
printf ( " db open error. " ) ;
return 1;
}
return 0;
}
int DatabaseExecute ( struct DBObj3 db, const char3 szSQL)
{
char3 pErrMsg = NULL;
int nErrorCode;
struct DB Info3 pDBinfo;
pDB info = ( structDB Info3 ) db —> priv;
nErrorCode = sqlite_exec ( ( struct sqlite 3 )(pDBinfo - > stConnect) ,
szSQL, NULL, NULL, &pErrMsg) ;
return nErrorCode;
}
可以看出,各個封裝函數(shù)是通過調(diào)用SQLite的API函數(shù)實現(xiàn)的。在基于Linux操作系統(tǒng)上使用SQLite,經(jīng)測試嵌入式數(shù)據(jù)庫響應(yīng)迅速,運行穩(wěn)定,用戶基本感覺不到命令延遲,在瀏覽聲音和圖像媒體時流暢自然,充分驗證了使用SQLite數(shù)據(jù)庫的優(yōu)越性。
5 總結(jié)
在經(jīng)過大量的分析對比之后,針對嵌入式系統(tǒng)開發(fā)的特點,從眾多數(shù)據(jù)庫發(fā)行版中選出非常適用的嵌入式數(shù)據(jù)庫SQLite。ARM-Linux下完成了對SQLite的編譯,并基于此在項目中作了進一步的開發(fā)工作。實踐證明,SQLite能夠出色地完成嵌入式系統(tǒng)中的數(shù)據(jù)庫應(yīng)用需求。
參考文獻
[1] 譚愛國,琚長江,余 濤.SQLite在基于L inux的Media NAS系統(tǒng)中的應(yīng)用[J]。武漢理工大學(xué)學(xué)報:信息與管理工程版, 2007, 29 (6)
[2] 曾立勝. 基于SQL ite嵌入式數(shù)據(jù)庫的射頻卡數(shù)據(jù)存儲[ J ]. 電腦知識與技術(shù), 2006 (8)
[3] 倪天龍,張賢高,王培.數(shù)據(jù)庫SQLite在嵌入式系統(tǒng)中的應(yīng)用[ J ]. 單片機與嵌入式系統(tǒng)應(yīng)用, 2005 (10) : 35 - 37.
[4] 萬瑪寧. 嵌入式數(shù)據(jù)庫典型技術(shù)SQLite和Berkeley DB的研究[J]. 微計算機信息,2006/02
[5] 王冠宇. JAVA在SQLite嵌入式數(shù)據(jù)庫中的應(yīng)用[J]. 微計算機信息,2006/02